为什么 f<$>g<$>x 和 (f.g)<$>x 相等,尽管<$>不是右结合的?

12

为什么 f <$> g <$> x 等价于 (f . g) <$> x,尽管 <$> 不是右结合的?

(这种等价性在 一种常用的习惯语境 中使用普通的 $ 是有效的,但当前的 $ 是右结合的!)

<*><$> 具有相同的结合性和优先级,但行为不同!

例如:

Prelude Control.Applicative> (show . show) <$> Just 3
Just "\"3\""
Prelude Control.Applicative> show <$> show <$> Just 3
Just "\"3\""
Prelude Control.Applicative> pure show <*> pure show <*> Just 3

<interactive>:12:6:
    Couldn't match type `[Char]' with `a0 -> b0'
    Expected type: (a1 -> String) -> a0 -> b0
      Actual type: (a1 -> String) -> String
    In the first argument of `pure', namely `show'
    In the first argument of `(<*>)', namely `pure show'
    In the first argument of `(<*>)', namely `pure show <*> pure show'
Prelude Control.Applicative> 
Prelude Control.Applicative> :i (<$>)
(<$>) :: Functor f => (a -> b) -> f a -> f b
    -- Defined in `Data.Functor'
infixl 4 <$>
Prelude Control.Applicative> :i (<*>)
class Functor f => Applicative f where
  ...
  (<*>) :: f (a -> b) -> f a -> f b
  ...
    -- Defined in `Control.Applicative'
infixl 4 <*>
Prelude Control.Applicative> 

根据<$>的定义,我预期show <$> show <$> Just 3也会失败。

1个回答

21
为什么 f <$> g <$> x 等同于 (f . g) <$> x?
这不是一个范畴学的问题,而是一个 Haskell 的问题。它之所以有效,是因为函数是范畴。两个 <$> 运算符作用于不同的范畴!
实际上,f <$> g 就等同于 f . g,所以你问的等式更加显然,即 f <$> (g <$> x) ≡ f . g <$> x

1
感谢您的聪明观察! - imz -- Ivan Zakharyaschev
嗯,我是指考虑另一个函子实例。也许,“观察”这个词不太合适。 - imz -- Ivan Zakharyaschev
故事的寓意是:对于函子(Functor)来说,(<$>) = (.)。 - AJF
1
(<$>) 函数用于函数函子,它将一个函数组合到一个作为函子的函数之前,该函子的 Functor 实例定义了 (<$>) 函数作为 (.) 函数,其功能是接受一个函数并产生一个函数,该函数接受一个函数并返回一个函数,该函数像两个组合在一起的函数一样运行。 - leftaroundabout
对于一个神秘地通过类型检查的代码,可以给出相同的解释(不确定该代码是否有其他错误或者是否仍然等同于原意):forever putStrLn "Hello, infinity" - imz -- Ivan Zakharyaschev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接