2015-04-12 57 views

回答

4

这是不可能的,你说的方式。

在您的类型签名中,初始函数只能使用m a,但您希望将其传递给m xm 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 ba -> m b,因为这可以让我们序列monadic动作,而不是转换monad,当我们想要操纵它们时更有意义。

+1

好的,谢谢@AJFarmer。我担心这是无法完成的,但不能明确地解释为什么;所以认为这值得问,如果只是为了澄清为什么不。关键似乎是fn在第一个arg通过实例化时被传递给了一个特定的a,除非我们按照您的说法使用rankNTypes。 – user3416536

+0

@ user3416536没错;类型变量是通过一个函数的类型传递的,并且不是隐含的,具有不同变量的两个类型是相等的,但是这是可能的。 'forall'只是说它可以在任何类型上工作,当然包括'm x'和'm y'! – AJFarmar