为什么"fmap(replicate 3)Just"在Haskell中有一种"a - > [Maybe a]"

Guo*_*eng 7 haskell types functor

最近我正在网上学习Haskell,学习Haskell for Great Good.

我有两个问题:

  1. fmap (replicate 3)是类型的Functor f=> f a -> f [a].为什么可以应用它Just

  2. 此外,为什么是fmap (replicate 3) Just类型a -> [Maybe a],而不是类型a -> Maybe [a]

bhe*_*ilr 13

如果你意识到你所处的fmap是一个功能而不是一个Maybe a价值,这很容易理解.类型Justa -> Maybe a,所以它属于(->) a仿函数,而不是Maybe仿函数.Functor函数的实例看起来像

instance Functor ((->) a) where
    fmap g f = g . f
Run Code Online (Sandbox Code Playgroud)

所以fmap只是成为正常的功能组合!这意味着

fmap (replicate 3) Just
Run Code Online (Sandbox Code Playgroud)

是相同的

replicate 3 . Just
Run Code Online (Sandbox Code Playgroud)

这显然有类型 a -> [Maybe a]


一个更"类型代数"的解释是排列类型并替换直到你不能再进行.让我们从我们的类型开始,但使用不同的变量名称,以便更容易遵循:

fmap      :: Functor f => (a -> b) -> (f a -> f b)
replicate :: Int -> c -> [c]
Just      :: x -> Maybe x
Run Code Online (Sandbox Code Playgroud)

然后fmap (replicate 3):

     (replicate 3) :: c -> [c]
fmap               :: (a -> b) -> (f a -> f b)
Run Code Online (Sandbox Code Playgroud)

所以

(c -> [c]) ~ (a -> b)
Run Code Online (Sandbox Code Playgroud)

这暗示着

c   ~ a
[c] ~ b
b   ~ [a]
Run Code Online (Sandbox Code Playgroud)

所以代替:

fmap (replicate 3) :: f c -> f [c]
Run Code Online (Sandbox Code Playgroud)

那么我们正在经历的fmapJust哪种类型

Just :: x -> Maybe x
Run Code Online (Sandbox Code Playgroud)

哪个可以用前缀形式重写为

Just :: (->) x (Maybe x)
Run Code Online (Sandbox Code Playgroud)

或者如果我们真的想要更多括号

Just :: ((->) x) (Maybe x)
Run Code Online (Sandbox Code Playgroud)

然后

                   Just :: ((->) x) (Maybe x)
fmap (replicate 3)      :: f        c         -> f [c]
Run Code Online (Sandbox Code Playgroud)

这暗示着

((->) x) (Maybe x) ~ f c
(->) x  ~ f
Maybe x ~ c
[c] ~ [Maybe x]
Run Code Online (Sandbox Code Playgroud)

所以代替:

fmap (replicate 3) :: ((->) x) (Maybe x) -> ((->) x) [Maybe x]
Run Code Online (Sandbox Code Playgroud)

并回到中缀符号

fmap (replicate 3) :: (x -> Maybe x) -> (x -> [Maybe x])
Run Code Online (Sandbox Code Playgroud)

然后申请Just:

fmap (replicate 3) Just :: x -> [Maybe x]
Run Code Online (Sandbox Code Playgroud)

我想在这里强调,那Maybe是一个Functor没有任何与本次减持,唯一Functor涉及的是功能Functor.列表也是一个Functor,但仅仅因为它出现在类型中replicate并不意味着它在这种情况下很重要.很容易与功能混淆

fmap (replicate 3) . Just :: a -> Maybe [a]
Run Code Online (Sandbox Code Playgroud)

但由于增加了,这完全不同..