首页 > 解决方案 > fmap 在 Nothing 上的 2-arity 函数应该返回 Nothing?

问题描述

来自ghcMaybe的来源:

instance Functor Maybe where
    fmap _ Nothing  = Nothing
    fmap f (Just a) = Just (f a)

fmap应用于时Nothing,它应该返回Nothing

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

Prelude> fmap (+1) Nothing
Nothing

但是,当我应用一个元数为 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

事实上,结果似乎是Nothing

Prelude> import Data.Maybe
Prelude Data.Maybe> isNothing $ fmap (++) Nothing
True

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

标签: haskellghci

解决方案


是的。让我们看一下类型:

fmap :: Functor f => (a -> b) -> f a -> f b
(++) :: [a] -> [a] -> [a]

所以,

fmap (++) :: Functor f => f [a] -> f ([a] -> [a])

fmap采用 1-arity 函数。然而,在 Haskell 中,2-arity 函数只是一个 1-arity 函数,它返回另一个 1-arity 函数:

([a] -> [a] -> [a]) ~ ([a] -> ([a] -> [a]))

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

如果你传递Nothing给它,它会返回Nothing. 如果您通过Just "foo"(例如),它会返回Just一个函数,该函数接受一个字符串并在"foo"其前面添加:

Prelude> Just f = fmap (++) $ Just "foo"
Prelude> f "bar"
"foobar"

您收到错误的原因是因为 GHCi 尝试打印输出,这意味着输出必须实现Show类型类。它试图做的showNothing :: Maybe ([a] -> [a]). 类型系统不知道它只需要 print Nothing,它只知道它不能show[a] -> [a]. 所以它打印错误。


推荐阅读