我在Haskell中有以下类型签名:
hi :: (b -> c) -> (a -> b) -> (a -> c)
我想写一个具体的实现,但我真的很难理解从哪里开始。我知道hi需要一个函数(b - > c),它返回一个函数(a - > b),它最终返回一个函数(a - > c)。
有人能告诉我一个具体实现的例子吗?我如何知道从哪里开始这样的事情以及定义左侧的内容?
答案 0 :(得分:26)
考虑到这一点的一种方法是使用(b -> c)
和(a -> b)
并返回另一个函数(a -> c)
的函数。那么让我们从
hi f g = undefined -- f :: b -> c, g :: a -> b
我们知道返回类型必须是函数(a -> c)
-
hi f g = \a -> undefined -- f :: b -> c, g :: a -> b
我们现在右侧有a
类型的东西,我们有一个函数g :: a -> b
所以一个明智的事情(事实上,我们唯一可以做的)是申请g
至a
hi f g = \a -> g a -- ok, this fails to typecheck...
表达式g a
的类型为b
,f :: b -> c
,我们希望最终得到c
。所以,我们只能做一件事 -
hi f g = \a -> f (g a)
这种类型检查!我们现在开始清理过程。我们可以将a
移动到等号的左侧
hi f g a = f (g a)
而且,如果您碰巧知道合成运算符.
,您可能会注意到它可以在这里使用
hi f g a = (f . g) a
现在a
双方都是多余的(这称为eta reduction)
hi f g = f . g
我们可以使用函数形式.
(.)
运算符拉到表达式的前面
hi f g = (.) f g
现在g
和f
都是多余的(另外两个eta减少应用)
hi = (.)
所以你的函数hi
只不过是函数组合。
答案 1 :(得分:3)
你读错了:->
运算符是右关联的。因此,您的签名是:(b->c) -> ((a->b) -> (a->c))
。所以你可以把它读作:给定一个从b
到c
的函数,它返回一个函数,它从a
到b
取一个函数,最后从{返回一个函数{1}}至a
。
从那里,你应该能够自己解决这个问题。