"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
是一个突出的例子。
Applicative
s 是 Functor
s 的扩展。使用 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
的值是值 Nothing
或 Just 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
甚至不是 Functor
(Applicative
的先决条件),但它仍然非常有用。事实证明,对等价于 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
一对,它会给你一个函数,反之亦然。
我正在尝试了解 Haskell 中的应用程序。无法弄清楚以下类型签名是什么意思:
f (a -> b)
例如:
foo :: Num a => Maybe (a -> a)
foo = Just (+1)
如何理解Maybe (a -> a)
的意思?它是一个函数吗?如果是,允许哪些类型的参数?
同样显然,我是函数式编程的新手,将不胜感激有关此主题的任何资源。
您可以将 f (a -> b)
想象成包含在上下文中的 a -> b
类型的函数。它主要用于 Applicative
的上下文中,Maybe a
是一个突出的例子。
Applicative
s 是 Functor
s 的扩展。使用 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
的值是值 Nothing
或 Just 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
甚至不是 Functor
(Applicative
的先决条件),但它仍然非常有用。事实证明,对等价于 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
一对,它会给你一个函数,反之亦然。