什么是Haskell中的'(浮动a,Num(a - > a))'?

时间:2015-11-14 04:56:40

标签: haskell

在Haskell中,我只知道

:type ((+)(1))
((+)(1)) :: Num a => a -> a
((+)(1) 2
3

但是怎么样

:type abs(sqrt)
abs(sqrt) :: (Floating a, Num (a -> a)) => a -> a

实际上,我尝试了很多次但是没有使用'abs(sqrt)'这个功能。然后我有几个问题。什么是类型(类?)'(浮动a,Num(a - > a))'?是否可以使用'abs(sqrt)'函数?怎么样?

3 个答案:

答案 0 :(得分:1)

当你看到Num (a -> a)时,通常意味着你在某个地方犯了错误。

也许你真的想要abs . sqrt,其类型为Floating c => c -> c - 即它是浮动类型(例如Float,Double)的函数,属于同一个浮动类型。

答案 1 :(得分:0)

可能无法使用此功能。

此处可能发生的是,该类型表明abs(sqrt)具有a必须属于类Floating(a -> a)必须属于类{的约束{1}}。换句话说,Num函数需要能够被视为数字。

不幸的是,sqrt不属于类sqrt,因此不会有任何输入在这里工作(不管它是否有意义)。但是,某些版本的GHCi允许您获得可能的类型。

请查看Haskell type length + 1类似问题。

正如ErikR所说,或许你打算写Num

答案 2 :(得分:0)

类型类是一种泛化函数的方法,这样它们可以是多态的,而其他类可以为它们自己的类型实现这些函数。以类型类Show为例,其简化形式为

class Show a where
    show :: a -> String

这表示实现Show类型类的任何类型都可以转换为String(对于更现实的约束,还有一些更复杂的问题,但是Show的要点是能够将值转换为String s)。

在这种情况下,函数show具有完整类型Show a => a -> String

如果我们检查函数sqrt,它的类型是

> :type sqrt
sqrt :: Floating a => a -> a

对于abs

> :type abs
abs :: Num b => b -> b

如果您询问GHCi的类型是什么,它会在两种情况下使用类型变量a,但我在b的类型签名中使用了abs来明确这些是同名的不同类型变量,它有助于避免下一步的混淆。

这些类型签名意味着sqrt获取其类型实现Floating类型类的值(使用:info Floating查看所有成员)并返回相同类型的值,并且abs函数接受一个类型实现Num类型类的值,并返回相同类型的值。

表达式abs(show)被等效地解析为abs sqrt,这意味着sqrt是传递给abs的第一个且唯一的参数。但是,我们只是说abs的值为Num类型,但sqrt是函数,而不是数字。为什么Haskell接受这个而不是抱怨?当我们使用类型签名执行替换时,可以更清楚地看到原因。由于sqrt的类型为Floating a => a -> a,因此必须与b的类型签名中的参数abs匹配,因此将b替换为Floating a => a -> a我们得到abs sqrt :: (Floating a, Num (a -> a)) => a -> a

Haskell实际上允许函数类型实现Num类型类,你可以自己做,尽管它可能是荒谬的。然而,仅仅因为某些东西对GHC来说似乎没有意义,只要这些类型可以干净利落地解决它就会允许它。

你无法真正使用这个功能,它只是没有意义。任何Num (a -> a)都没有a的内置实例,因此您必须定义自己的abs。但是,您可以使用合成运算符sqrt 撰写函数.> :type abs . sqrt abs . sqrt :: Floating c => c -> c

myfunc x = abs (sqrt x)

这确实有意义。此功能相当于

x

请注意,sqrt首先应用于abs,然后将该计算的结果传递给sqrt,而不是将函数abs传递给{{} 1}}。