定义具有可能签名的haskell函数

时间:2017-07-28 02:41:32

标签: haskell

我不清楚如何在haskell中编写函数签名,尤其是使用Maybe。考虑:

f :: Maybe a -> Maybe a
f = \a -> a

main = print (f (Just 5))

这可行,但为什么功能签名不能这样呢?

f :: Maybe -> Maybe 

因为f只采用Maybe类型并返回Maybe类型。

相关:如果我想让Maybe类型更具体并且是Maybe Int,为什么这不起作用?

f :: Maybe Int a -> Maybe Int a
f = \a -> a

main = print (f (Just (Int 5)))

(我正在使用runhaskell test.hs运行所有代码)

2 个答案:

答案 0 :(得分:10)

好像你对类型变量感到困惑。首先,在

f :: Maybe a -> Maybe a
f = \a -> a

第一行中的a与第二行中的a无关,我们可以这样写:

f :: Maybe a -> Maybe a
f = \x -> x

甚至

f :: Maybe foo -> Maybe foo
f = \bar -> bar

a是代表类型的变量。因此f声明f同时包含大量类型:

f :: Maybe Int -> Maybe Int
f :: Maybe String -> Maybe String
f :: Maybe (Maybe Bool) -> Maybe (Maybe Bool)
...

等等。正如我怀疑你所想的那样,这不是一些“标记”的论点。两个a相同的事实意味着参数类型必须是相同的结果类型。如果我们说f :: Maybe a -> Maybe b我们会得到这个家庭:

f :: Maybe Int -> Maybe Bool
f :: Maybe String -> Maybe String
f :: Maybe (Maybe Bool) -> Maybe Int
...

也就是说,ab现在可以代表不同的类型,但参数和结果仍然必须是Maybe

你不能说的原因

f :: Maybe -> Maybe

是因为Maybe不是类型 - 它是类型构造函数。如果你给它一个类型,它会给你一个类型。因此,Maybe IntMaybe String是类型,只要Maybe a是类型,a就是一种类型。

Maybe Int a(解析为(Maybe Int) a)没有意义,因为Maybe Int不是类型构造函数 - 它不再接受任何参数。

建议阅读:来自LYAH的Types and Typeclasses

答案 1 :(得分:5)

endpointConfiguration.DisableFeature<TimeoutManager>(); 是一个类型构造函数,本质上是一个类型级函数。它需要一个类型(例如Maybe)并返回一个类型(例如Int)。类型的“类型”称为 types :具有值的类型(如Maybe Int)称为Int。采用一个参数的类型构造函数的类型是*。您可以使用* -> * / :kind命令在GHCi中看到此内容:

:k

> :k Int Int :: * > :k Maybe Maybe :: * -> * > :k Either Either :: * -> * -> * 之类的签名中,Maybe a -> Maybe a是一个类型变量,在您调用该函数时会被特定类型替换。 (隐含地,这意味着a,如果您启用forall a. Maybe a -> Maybe aExplicitForall等扩展程序,则可以自行编写。{/ p>

因此,如果您在ScopedTypeVariables上致电f :: Maybe a -> Maybe a,那么Maybe Int在该呼叫网站上的类型为f,因为Maybe Int -> Maybe Int已经实例化a

编译器拒绝Int,因为当它只接受一个参数时,你会向Maybe Int a提供两个参数。 (Maybe不是参数的名称,而是类型的参数。)同样,它拒绝a,因为您没有给Maybe -> Maybe参数,所以你正在尝试将两种类型的Maybe传递给函数箭头构造函数* -> *,它接受​​类型为(->)的参数:

*

顺便说一句,可以写一些类似> :k (->) (->) :: * -> * -> * 的内容并将其扩展为Maybe -> Maybe,这有时会很有用,但几乎肯定不是你想要做的事情现在

Maybe a -> Maybe a

此处,类型同义词{-# LANGUAGE RankNTypes #-} {-# LANGUAGE TypeOperators #-} type (~>) f g = forall a. f a -> g a f :: Maybe ~> Maybe f x = x 扩展为Maybe ~> Maybe,可以缩写为forall a. Maybe a -> Maybe a,即您之前编写的签名。