从签名实现 Haskell 函数

0 haskell

我试图围绕 Haskell 进行思考,但在尝试将以下签名实现为函数时遇到了麻烦。你们能给我一个使用 lambda 表达式的例子吗?

(b -> c) -> (a -> b) -> a -> c
Run Code Online (Sandbox Code Playgroud)

Sim*_*ine 5

首先尝试使用更简单的示例。例如,

f :: a -> a
f = ...
Run Code Online (Sandbox Code Playgroud)

由于f是一个参数的函数,我们可以将其扩展为:

f :: a -> a
f = \x -> ...
Run Code Online (Sandbox Code Playgroud)

为这个函数选择一个返回值,我们正好有一个很好的候选,x,所以:

f :: a -> a
f = \x -> x
Run Code Online (Sandbox Code Playgroud)

虽然我们也可以选择undefinederror "meh", 或f x,它们不太有用。


这是另一个简单的例子:

g :: (a, b) -> (b, a)
g = ...
Run Code Online (Sandbox Code Playgroud)

与函数输入匹配的唯一模式是一对,因此:

g :: (a, b) -> (b, a)
g = \(x, y) -> ...
Run Code Online (Sandbox Code Playgroud)

这并不具有等同于swap,但它是一个很好的选择,因为它终止。


最后一个更复杂的例子:

h :: ((a, b) -> c) -> a -> b -> c
h = ...
Run Code Online (Sandbox Code Playgroud)

这是一个类型为(a, b) -> c, aand的三个参数的函数b,所以不用多想,我们可以部分扩展答案:

h :: ((a, b) -> c) -> a -> b -> c
h = \f -> \x -> \y -> ...
h = \f x y -> ...
Run Code Online (Sandbox Code Playgroud)

(下一行只是一种堆叠柯里化参数的便捷方式。)

现在,我给他们的名字fx而且y因为我觉得f是一个包含值的好,通用名->,并xy好,为任意值的通用名称。我也可以选择ab加强同名类型之间的联系,但这也会有点混乱。所以在这里,x :: ay :: b

至于填写函数体,我可以问“我如何应用我拥有的东西以使类型对齐”,或者我可以查看返回类型c,然后查看我可以制作的内容类型的值c。如果我给它一对 type ,则f返回。我有一个和一个,所以:c(a, b)x :: ay :: b(x, y) :: (a, b)

h :: ((a, b) -> c) -> a -> b -> c
h = \f x y -> f (x, y)
Run Code Online (Sandbox Code Playgroud)

这是顺带一提curry。我认为您找不到任何其他终止的解决方案?

对于简单的函数,通常只有一个好的候选者。当你有多个相同类型值的类型签名时,你必须考虑如果你选择一个而不是另一个会发生什么。我能想到的第一种情况是当你>>=为 state monad实现操作符时。