函数签名类型中的Haskell函数

时间:2016-02-21 18:53:09

标签: haskell

我正在努力理解Haskell中函数签名类型中的函数, 我见过这个功能;

$('.photo-list').on('click', function (event) {
console.log("HELLO!");
});

在参数上选择的函数的两倍。我理解f是一个函数,但不明白为什么我们有签名类型twice :: (a -> a) -> a -> a twice f x = f(f x) 我认为这将是(a -> a) -> a -> a,因为

  1. 您提供了一个参数,因此函数的输入必须接受a的类型。
  2. b是函数的输出类型,因此整体输出类型为b。
  3. 我是Haskell的新手:)

2 个答案:

答案 0 :(得分:4)

让我们看看会发生什么!

twice :: (a -> b) -> a -> b
twice f x = f (f x)

只需阅读twice的类型,我们立即知道:

f :: a -> b
x :: a

因此:

f x :: b

如果f :: a -> bf x :: bf (f x)的类型是什么?我们不知道是否a = b,因此我们不知道是否可以将f x应用于f。如果我们不知道那么我们就无法安全地编译该程序。

Couldn't match expected type `a' with actual type `b'
...
In the first argument of `f', namely `(f x)'
In the expression: f (f x)

答案 1 :(得分:0)

你是对的,函数的类型也可以用更通用的形式(a -> b) -> a -> b来编写。但是,f (f x)会出现轻微问题:f x的结果为b,但外f期望其参数的类型为a。因此ab实际上必须是同一类型!你可以把它写成

twice :: (a~b) => (a -> b) -> a -> b

其中a~b等式约束(您需要其中一个GHC扩展TypeFamiliesGATDs,因此这是可接受的)。但如果两者都是相同的类型,你也可以立即给它们相同的名字......例如,a。这简化了签名

twice :: (a -> a) -> a -> a