"f (a -> b)" 类型签名在 Haskell 中是什么意思?

What does "f (a -> b)" type signature mean in Haskell?

我正在尝试了解 Haskell 中的应用程序。无法弄清楚以下类型签名是什么意思:

f (a -> b)

例如:

foo :: Num a => Maybe (a -> a)
foo = Just (+1)

如何理解Maybe (a -> a)的意思?它是一个函数吗?如果是,允许哪些类型的参数? 同样显然,我是函数式编程的新手,将不胜感激有关此主题的任何资源。

您可以将 f (a -> b) 想象成包含在上下文中的 a -> b 类型的函数。它主要用于 Applicative 的上下文中,Maybe a 是一个突出的例子。

Applicatives 是 Functors 的扩展。使用 Applicative 的典型示例是具有多个参数的函数。

如果我们有两个 Maybe Int 要加起来怎么办。我们可以尝试部分应用 +fmap 又名 <$>。因此我们可以尝试:

f :: Maybe (Int -> Int)
f = (+) <$> Just 3

但是现在,我们如何将其应用于第二个参数。这就是我们需要 Applicative 类型类的地方。它定义了 <*> 函数。它的类型是

<*> :: Applicative f => f (a -> b) -> f a -> f b

因此我们可以使用它来将第二个 Maybe Int 应用到我们部分应用的函数 f 中:

> f <*> Just 4
Just 7

没有辅助函数 f 语法类似于标准函数应用程序:

> (+) <$> Just 3 <*> Just 4
Just 7

如需进一步参考,请参阅 learnyouahaskell 的 applicative functors 章节。

在函数式编程中,函数与数字或任何其他类型的值没有太大区别。实际上,唯一的区别是您使用函数的方式是将其应用于参数。

类型 Maybe a 的值是值 NothingJust x,其中 x 是类型 a。所以如果你有一个 Maybe (a -> a) 类型的值,就像你的 foo,它要么是 Nothing,要么是 Just f,其中 f 是一个函数 a -> a。以最不花哨的方式,你会像这样使用它:

case foo of
    Nothing -> "There was no function"
    Just f -> "There was a function, and its value at 0 is " ++ show (f 0)

所以如果 foo 不是 Nothing,那么它包含 Just 一个函数作为它的值。


@Erich 是对的,尤其是文字表达式 f (a -> b) 很可能与应用函子有关,但不一定如此。例如,我最喜欢的类型是同构类型——两种类型之间的等价:

data Iso a b = Iso (a -> b) (b -> a)

Iso 甚至不是 FunctorApplicative 的先决条件),但它仍然非常有用。事实证明,对等价于 Bool 中的函数。我们可以将这样的等价构造为 Iso 值:

pairEquiv :: Iso (a,a) (Bool -> a)
pairEquiv = 
    Iso (\(x,y) -> \b -> if b then x else y) -- from pair to function
        (\f -> (f True, f False))            -- from function to pair

这里 (Bool -> a) 作为类型构造函数的参数出现,它只是意味着如果你给 Iso 一对,它会给你一个函数,反之亦然。