fmap一个2-arity函数Nothing应该返回Nothing?

Dap*_* Li 1 haskell ghci

从源头MaybeGHC:

instance Functor Maybe where
    fmap _ Nothing  = Nothing
    fmap f (Just a) = Just (f a)
Run Code Online (Sandbox Code Playgroud)

什么时候fmap应用Nothing,它应该返回Nothing.

例如,在ghci(v8.2.2)中运行它:

Prelude> fmap (+1) Nothing
Nothing
Run Code Online (Sandbox Code Playgroud)

但是,当我应用一个arity为2的函数时:

Prelude> fmap (++) Nothing
<interactive>:11:1: error:
    • No instance for (Show ([a0] -> [a0]))
        arising from a use of ‘print’
        (maybe you haven't applied a function to enough arguments?)
    • In a stmt of an interactive GHCi command: print it
Run Code Online (Sandbox Code Playgroud)

事实上,结果似乎是Nothing:

Prelude> import Data.Maybe
Prelude Data.Maybe> isNothing $ fmap (++) Nothing
True
Run Code Online (Sandbox Code Playgroud)

我的问题是,fmap (++) Nothing真的回归了Nothing吗?

Dar*_*nec 7

是.我们来看看类型:

fmap :: Functor f => (a -> b) -> f a -> f b
(++) :: [a] -> [a] -> [a]
Run Code Online (Sandbox Code Playgroud)

所以,

fmap (++) :: Functor f => f [a] -> f ([a] -> [a])
Run Code Online (Sandbox Code Playgroud)

fmap采用1-arity功能.但是,在Haskell中,2-arity函数只是一个1-arity函数,它返回另一个1-arity函数:

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

所以你的 fmap (++) :: Maybe [a] -> Maybe ([a] -> [a])

如果你传递Nothing给它,它会返回Nothing.如果你传递Just "foo"(例如),它返回Just一个带有字符串并在"foo"其前面的函数:

Prelude> Just f = fmap (++) $ Just "foo"
Prelude> f "bar"
"foobar"
Run Code Online (Sandbox Code Playgroud)

出现错误的原因是GHCi尝试打印输出,这意味着输出必须实现Show类型类.它正在尝试的show是什么Nothing :: Maybe ([a] -> [a]).类型系统不知道它只需要打印Nothing,它只知道它不能show是一个[a] -> [a].所以它打印错误.