我有以下的应用表达式,我知道这是错误的:
Prelude> [Just (*2), Just (+9)] <*> [(Just 3),(Just 4), (Just 5)]编译器抱怨:
<interactive>:2:2: error:
* Couldn't match expected type `Maybe Integer -> b'
with actual type `Maybe (Integer -> Integer)'
* Possible cause: `Just' is applied to too many arguments
In the expression: Just (* 2)
In the first argument of `(<*>)', namely `[Just (* 2), Just (+ 9)]'
In the expression:
[Just (* 2), Just (+ 9)] <*> [(Just 3), (Just 4), (Just 5)]
* Relevant bindings include it :: [b] (bound at <interactive>:2:1)编译器想说什么?
此错误消息:
* Couldn't match expected type `Maybe Integer -> b'
with actual type `Maybe (Integer -> Integer)'意思是表达式的这一部分[Just (*2), Just (+9)]?
让我们看看函数(<*>)的签名
(<*>) :: f (a -> b) -> f a -> f b用上面的List和Maybe类型构造函数替换它:
(<*>) :: [] (Maybe Integer -> b) -> [] (Maybe Integer) -> [] bb应该有哪种类型的?
发布于 2017-08-22 07:42:07
让我们更小心地替换
(<*>) :: (Applicative f) => f (a -> b) -> f a -> f b
[Just (*2), Just (+9)] :: [Maybe (Int -> Int)] --wlog
[Just 3, Just 4, Just 5] :: [Maybe Int]因此,f = [],因此:
(<*>) :: [a -> b] -> [a] -> [b]但是现在我们要将[a -> b]与[Maybe (Int -> Int)]相匹配,这是不可能的--一个函数和一个Maybe是不一样的。您正在尝试在两个函式下执行函式应用程式,而不只是一个函式。也就是说,你需要某种类型的东西
f (g (a -> b)) -> f (g a) -> f (g b)幸运的是,这很容易实现:liftA2 (<*>)。
或者,如果您想要更好的东西,您可以使用复合函子Compose [] Maybe。
getCompose $ Compose [Just (*2), Just (+9)] <*> Compose [Just 3, Just 4, Just 5](但当Compose很酷的时候,您并不是立即将其作为getCompose,而是将它作为您正在编写的任何程序中的一个重要抽象。)
发布于 2017-08-22 07:42:38
编译器引用了代码的这一部分(In the expression: Just (* 2)):
[Just (*2), Just (+9)] <*> [(Just 3),(Just 4), (Just 5)]
^^^^^^^^^它还说,实际的Just (*2)类型是Maybe (Integer -> Integer),但是使用它的方式需要一个Maybe Integer -> b类型的值(对于某些类型的b)。
如果你看看
(<*>) :: f (a -> b) -> f a -> f b您可以看到,第一个参数必须是应用于函数类型f的某种类型构造函数a -> b。您有一个值列表,所以f是[]。
因此,第一个参数必须是一个函数列表,但是您拥有的是一个Maybe的列表,这就是为什么这段代码是一个错误。
错误消息的其余部分来自<*>的第二个参数[(Just 3),(Just 4), (Just 5)],它是一个参数列表(用于第一个参数中的函数列表)。也就是说,编译器知道它需要一个f a类型的值,并且您给它[(Just 3),(Just 4), (Just 5)],所以它推导了f = [],a = Maybe Integer。
因此,第一个参数f (a -> b)的类型变为[] (Maybe Integer -> b) (与[Maybe Integer -> b]相同)。这里b是完全免费的。您可以使用任何您想要的结果类型,并且您将从f b (即[b] (一个结果列表))中得到<*>。
发布于 2017-08-22 07:39:22
这里有一个错误的替代:
(<*>) :: [] (Maybe Integer -> b) -> [] (Maybe Integer) -> [] b[Just (*2), Just (+9)]有以下类型:Num a => [Maybe (a -> a)]
那是因为List是f in (<*>) :: f (a -> b) -> f a -> f b。
根据(<*>)的类型,您可以拥有:
[(*2), (+9)] <*> [2, 3]或
Just (*2) <*> Just 2在这些表达式中,[]和Maybe将是相应的应用上下文,而不是同时使用(<*>)。
以下深奥的表达式将编译:
[(Just (*2) <*>), (Just (+9) <*>)] <*> [(Just 3), (Just 4), (Just 5)]但我不确定你要找的是什么。
https://stackoverflow.com/questions/45811310
复制相似问题