Haskell Applicative []为什么我不能用函数中的[]替换pure []?

时间:2014-04-05 08:08:44

标签: haskell applicative

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 [])会导致相同的结果..谁可以向我解释这些差异?

2 个答案:

答案 0 :(得分:15)

pure的类型为Applicative f => a -> f apure []

的类型为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)中运行,因此它选择fIO,并显示结果列表[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'中定义