2015-04-12 2 views
2

Возможно ли построить функцию, которая будет отображать кортеж монадов произвольной arity?Haskell: как отобразить функцию над произвольным набором монад

например,

f :: (m a -> m [a]) -> (m x, m y) -> (m [x], m [y]) 

(но для произвольной арности). This similar question, имеет ряд перспективных предложений; например, линзы 'each или over both, но каждый из них, по-видимому, требует кортежа гомогенных типов: я хочу использовать кортеж гомогенных монадов с различными внутренними типами.

ответ

4

Невозможно так, как вы говорите.

В вашей подписи типа, начальная функция может принимать только в m a, но вы ожидаете, передать ему m x и m y, поэтому типы не совпадают.

Это, конечно, можно сделать это с rankNTypes поддержкой:

{-# LANGUAGE rankNTypes #-} 
f :: Monad m => (forall a. m a -> m [a]) -> (m x, m y) -> (m [x], m [y]) 
f fun (x, y) = (fun x, fun y) 

Это потому, что forall a. внутри скобок заставляет его быть полиморфными, а не только для типа a.


То, что вы, вероятно, хотите что-то вроде этого:

f :: Monad m => (a -> m b) -> (m a, m a) -> (m b, m b) 

или даже

f :: Monad m => (a -> m c) -> (b -> m d) -> (m a, m b) -> (m c, m d) 

Обратите внимание, что я изменил тип функции от m a -> m b к a -> m b, потому что позволяет нам а не превращать монаду, что имеет больше смысла, когда мы хотим манипулировать ими.

+1

Хорошо, спасибо @AJFarmer. Я боялся, что это невозможно сделать, но не может явно объяснить причину; поэтому подумал, что стоит спросить, если только уточнить, почему нет. Кажется, ключ состоит в том, что fn, переданный как первый arg, привязан к одному конкретному a в момент создания экземпляра, если мы не будем использовать rankNTypes, как вы говорите. – user3416536

+0

@ user3416536 это правильно; переменные типа переносятся по типу функции, и неясно, что два типа с разными переменными равны, но это возможно. 'forall' просто говорит, что он может работать на любом типе, который, конечно же, включает' m x' и 'm y'! – AJFarmar

Смежные вопросы