ghci> :t pure []
pure [] :: Applicative f => f [a]
ghci> pure []
[]
ghci> :t []
[] :: [a]
ghci> fmap ((:) 2) (pure [])
[2]
ghci> fmap ((:) 2) ([])
[]
我原本以为在pure[]
中用[]
替换fmap ((:) 2) (pure [])
会导致相同的结果..谁可以向我解释这些差异?
答案 0 :(得分:15)
pure
的类型为Applicative f => a -> f a
,pure []
的类型为Applicative f => f [a]
。您可以为不同的应用类型明确指定f
,例如
pure [] :: Maybe [String] //Just []
pure [] :: IO [String] //displays '[]' in ghci
pure [] :: [[String]] //[[]]
fmap ((:) 2) (pure [])
的类型为(Applicative f, Num a) => f [a]
。由于Ghci在IO monad(Applicative
)中运行,因此它选择f
为IO
,并显示结果列表[2]
,这就是您所看到的。
您可以直接指定应用类型以查看不同的结果,例如
fmap ((:) 2) (pure []) :: (Maybe [Int])
是Just [2]
在fmap ((:) 2) ([])
中,输入列表中没有元素,因此您将获得一个空列表。
答案 1 :(得分:5)
为什么会它是一样的?他们的表达方式不同。
如果我们只看列表,也许它会简化事情。所以,有空列表[]
。它的类型可以是围绕它的括号,特别是嵌套列表:
前奏> [] :: [[Int]]
[]
但是还有另一个“空嵌套列表”:
前奏> [[]] :: [[Int]]
[[]]
这个并不是空的,只是只包含空列表。 ([[],[],[],...]
也是可能的)。事实上,如果在列表应用程序中完成,那将是您尝试过的结果:
Prelude Control.Applicative> pure [] :: [[Int]]
[[]]
它肯定与空列表不一样,
前奏> [[]] == []
假
特别是
前奏> (长度[],长度[[]])
(0,1)
并且fmap
对空列表进行操作永远不会做任何事情,而fmap
对包含空的列表进行ping操作将使用[]
调用该函数:一种简单的方法来查看它是< / p>
Prelude Control.Applicative&gt; fmap undefined []
[]
Prelude Control.Applicative&gt; fmap undefined [[]]
[ * 例外:Prelude.undefined
关于你的审判真正令人困惑的事情是ghci默默使用IO
monad。
还有一个Applicative
的子类用于实际空虚:
Prelude Control.Applicative&gt; :我的替代品 class Applicative f =&gt;替代f其中
空:: f a
(&lt; |&gt;):: f a - &gt; f a - &gt; f a
some :: f a - &gt; f [a]
很多:: f a - &gt; f [a]
- 在“Control.Applicative”中定义 实例Alternative [] - 在`Control.Applicative'中定义 实例Alternative Maybe - 在`Control.Applicative'中定义