Just (+) <*> Just 3 <*> Just 5
只是8
pure (+) <*> Just 3 <*> Just 5
只是8
pure (*3) <*> [0..10]
[0,3,6,9,12,15,18,21,24,27,30]
Just (*3) <*> [0..10]
无法将类型'[]'与'Maybe'匹配
预期类型:也许b
实际类型:[b]
在'(&lt; *&gt;)'的第二个参数中,即'[0 .. 10]'
在表达式中:Just(* 3)&lt; *&gt; [0 .. 10]
在'it'的等式中:it = Just(* 3)&lt; *&gt; [0 .. 10]
pure
和Just
何时可以互换,何时不同?
答案 0 :(得分:10)
pure
是一个重载操作。它是为实现Applicative
类的所有类型定义的。其中一种类型是Maybe
。因此,pure
在该上下文中与Just
相同。但是还有其他类型也实现了Applicative
,例如[]
(列表)。在这种情况下,pure
表示单例(即获取单个值并返回包含该值的单元素列表的函数)。所以
pure (*3) <*> [0..10]
真的意味着:
[(*3)] <*> [0..10]
而不是
Just (*3) <*> [0..10]
在最后一个例子中,你试图将列表与maybes混合,这就是GHC拒绝它的原因。一般来说,haskell根据上下文确定pure
的确切含义,例如如果您尝试将其与maybes一起使用,它会将其解释为Just
,如果您将其用于列表,则将其解释为单身。
答案 1 :(得分:6)
pure
函数返回多态值:
Prelude> :t pure "foo"
pure "foo" :: Applicative f => f [Char]
对于Maybe
,pure
刚定义为Just
:
instance Applicative Maybe where
pure = Just
-- ...
其他类型提供不同的定义;例如,它被列为
列表instance Applicative [] where
pure x = [x]
-- ...
指定返回值的类型告诉Haskell Applicative
实例用于定义pure
。
Prelude> pure "foo" :: [[Char]]
["foo"]
Prelude> pure "foo" :: Maybe [Char]
Just "foo"
除了提供显式类型之外,Haskell还可以根据值的使用方式推断使用哪种类型。例如,(<*> [1..5]) :: (Num a, Enum a) => [a -> b] -> [b]
,因此在pure (+3) <*> [1..5]
中,我们知道pure (+3)
必须包含[a -> b]
类型。同样,在pure (+3) <*> Just 5
中,我们知道pure (+3)
必须具有Maybe (a->b)
类型。
通常,在任何表达式pure f <*> g
中,g
的类型将确定需要返回的值pure f
的类型。