Haskell函数的类型(num - > num) - > NUM

时间:2018-03-20 15:53:08

标签: haskell types functional-programming

我正在努力研究R. Bird的函数式编程书中的练习,该书要求使用类型(num - > num) - >的函数的示例。 NUM

我能想到的最好的是多态类型

func1 f = f 3
:t func1
func1 :: Num t1 => (t1 -> t2) -> t2

我遇到的问题是我无法指定f的返回类型,因此类型仍为(num - > t2) - > T2。

我强制返回f类型的尝试如下:

square x = x * x
:t func1 square
func1 square :: Num t2 => t2 -> t2

因为当然如果我试图找到func1∘square的类型,它将只是num - > NUM

2 个答案:

答案 0 :(得分:3)

如果足以提供可以分配该类型的功能,那么你的已经足够了。也就是说,以下类型检查就好了:

func1 :: Num a => (a -> a) -> a
func1 f = f 3

另一方面,如果你想要一个被推断为具有该类型的函数,那么你需要做一些技巧。我们在这里要做的是指定f 3的结果和我们输入的3具有相同的类型。强制两个术语具有相同类型的标准方法是使用asTypeOf,这是以这种方式实现的:

asTypeOf :: a -> a -> a
asTypeOf x _ = x

所以,试试吧:

> :t \f -> f 3 `asTypeOf` 3
(Num a, Num t) => (t -> a) -> a

对我们来说不幸的是,这不起作用,因为3中的f 3和独立的3被推断为使用可能不同的 Num的实例。不过,它比\f -> f 3更接近 - 请注意我们之前没有输出的新Num a约束。明显的下一个想法是let - 将变量绑定到3并将该变量重用为fasTypeOf的参数;当然GHC会得到f的论点和结果具有相同类型的图片,对吗?

> :t \f -> let x = 3 in f x `asTypeOf` x
(Num a, Num t) => (t -> a) -> a

讨厌鬼。事实证明let做了所谓的"让我们进行推广&#34 ;; x将与3一样多态,并且可以专门针对不同使用站点的不同类型。通常这是一个很好的功能,但因为我们做了一个不自然的运动,我们需要做一些不自然的事情......

好的,下一个想法:一些lambda calculi不包含let,当你需要一个时,而不是写let a = b in c,你写(\a -> c) b。这对我们来说特别有趣,因为Haskell使用特殊限制的多态,这意味着在c内,a的类型是单态。所以:

> :t \f -> (\x -> f x `asTypeOf` x) 3
Num a => (a -> a) -> a

现在你抱怨asTypeOf作弊,因为它使用了与其推断类型不匹配的类型声明,而练习的重点是通过推理单独获得正确的类型。 (如果我们可以使用与推断类型不匹配的类型声明,我们可以在开始时从func1 :: Num a => (a -> a) -> a; func1 f = f 3停止!)好的,没问题:还有另一个标准强制两个表达式的类型统一的方法,即将它们放在一个列表中。所以:

> :t \f -> (\x -> head [f x, x]) 3
Num a => (a -> a) -> a
Phew,现在我们终于可以在原则上从头开始构建所需的所有工具,无需任何类型声明即可获得正确类型的术语。

答案 1 :(得分:0)

func1 f = let x = f x in x这是一个部分功能,它在技术上具有您想要的类型,您应该知道它们是什么以及它们在haskell中的工作方式。