3

我正在阅读关于应用函子的LYAH 章节,但我似乎不理解以下示例:

ghci> :t fmap (++) (Just "hey")  
fmap (++) (Just "hey") :: Maybe ([Char] -> [Char])

但是当我看到这个时:

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

我确实了解(*3)(++"this")之类的内容如何适合(a -> b)类型,但我只是看不到[a] -> [a] -> [a]适合(a -> b)吗?

4

5 回答 5

7

关键是->关联到右边,所以一个like的类型a -> b -> c是真的a -> (b -> c)。所以[a] -> [a] -> [a]适合c -> d通过设置c~[a]d~ [a] -> [a]。您可以将函数[a] -> [a] -> [a]视为返回类型结果的 2 个参数的[a]函数,或返回类型结果的 1 个参数的函数[a] -> [a]

于 2012-08-24T13:11:29.473 回答
6

要意识到的是bin a -> b不一定是标量 - 它可以是一个函数。

[a] -> [a] -> [a]可以认为[a] -> ([a] -> [a])b[a] -> [a]

于 2012-08-24T13:10:36.223 回答
5

像往常一样把东西并排放置,

fmap :: Functor f => ( a    ->      b      )   ->      f a        ->   f b
fmap                       (++)                    (Just "hey")   ::   f b
(++) ::               [c]   -> ([c] -> [c])

所以,

a ~ [c]  ,    b ~ ([c] -> [c])  ,    f ~ Maybe  ,    a ~ [Char]  ,   c ~ Char

f b ~ Maybe b ~ Maybe ([c] -> [c]) ~  Maybe ([Char] -> [Char])

这里不涉及任何思考。类型的统一是一个机械过程。


并回答您的具体问题(释义),“如何[c] -> [c] -> [c]a -> b匹配,这里是:

  • 在类型签名中省略括号是邪恶的(在向新手教授 Haskell 时)
  • 在 Haskell 中,没有二进制函数。每个函数都是一元的。
  • 因此(正如其他人已经提到的),类型签名中的箭头与 right 相关联
于 2012-08-24T13:22:54.857 回答
4

这真的很简单:-)。让我添加一个简单的括号:

[a]->[a]->[a]就好像[a]->([a]->[a])

因此,它可以a->b通过替换 a by[a]和 b by来适应[a]->[a]。你给 ++ 一个字符串,然后你得到一个类型的函数作为string->string回报

fmap (++) (Just "hey") 是一个可能的 monad,它持有一个将字符串“hey”前缀到另一个字符串的函数。它确实是类型Maybe ([Char] -> [Char])

于 2012-08-24T13:09:56.057 回答
4

考虑一下 Maybe 类型的 fmap 定义。

fmap f (Just x) = Just (f x)

你的例子看起来像

fmap (++) (Just "Hey") = Just ("Hey" ++) :: Maybe ([Char] -> [Char])

正如 fmap 应该的那样,您只需在 Maybe 容器中解除 (++) 函数并将其应用于内容。

于 2012-08-24T13:13:58.683 回答