我有以下应用表达式,我知道这是错误的:
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) -> [] b
b
应该是哪种类型有吗?
最佳答案
让我们更仔细地替换
(<*>) :: (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
不可能相同。您正在尝试在 两个 仿函数下进行函数应用,而不仅仅是一个。 IE。你需要一些类型的东西
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
结果,而是将其用作您正在编写的任何程序中的重要抽象。)
关于haskell - 编译器是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45811310/