从源头Maybe
在GHC:
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
吗?
是.我们来看看类型:
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]
.所以它打印错误.