作者:爵士独舞 | 来源:互联网 | 2022-12-07 10:59
我无法找到以下的好手册:如果我想在Haskell中获得功能的定义,那么我使用:t
So例如:
:t sqrt
:t (+)
:t truncate
我会得到:
sqrt :: Floating a => a -> a
(+) :: Num a => a -> a -> a
truncate :: (RealFrac a, Integral b) => a -> b
我只是不确定如何理解这里的语法,关于on =>
和->
.我知道::
关于函数的定义,但其余的意思是关于函数定义.这对于理解一般的功能非常重要.
1> leftaroundab..:
我知道::
关于定义函数
呃没有.::
意味着你要给出一个类型签名,这不一定与定义函数有关(虽然在实践中,你应该为你编写的每个函数赋予一个类型签名,即使你没有,编译器也会推断签名).
sqrt :: Double -> Double -- } type signature
sqrt 0 = 0 -- ?
sqrt 1 = 1 -- ?
sqrt 2 = 1.4 -- should do -- ? definition
sqrt 4 = 2 -- ?
sqrt _ = error "too hard" -- ?
现在 - 正如您所见,这些签名实际上有点不同,而不仅仅是Double -> Double
.具体来说,签名sqrt :: Floating a => a -> a
被解析为
sqrt :: forall a .
(Floating a)
=> (a -> a)
这意味着,这实际上适用于所有类型a
(包括但不限于Double
),前提是它们具有instance Floating
.即,类型必须支持Floating
类的接口.对于这些类型中的每一种,签名将是"自身类型",即
sqrt :: Double -> Double
sqrt :: Complex Double -> Complex Double
sqrt :: Float -> Float
sqrt :: ExactSymbolic -> ExactSymbolic
但不是例如sqrt :: String -> String
,因为String
它不是一个实例Floating
,也不Bool -> Char
是甚至不匹配a -> a
模式.
对于其他示例,它类似:
(+) :: Num a => a -> a -> a
定义了可以用作例如操作员Int -> Int -> Int
或者Rational -> Rational -> Rational
,在所有类型的Num
类.
truncate :: (RealFrac a, Integral b) => a -> b
实际上可以在两种不同类型之间进行转换,例如Double -> Int
或Rational -> Integer
.要求是参数在RealFrac
类中,而结果在Integral
类中.
如何定义所有这些函数是另一回事 - 类型签名并没有告诉你(虽然对于特别"基本"的函数,实际上可能只有一种合理的方法来实现它给定类型签名).要查看函数的定义方式,您需要查看源代码.这通常与Haddock文档Source
链接,签名的小链接权限.对于像你这样的内置函数(+)
,Double
你不会找到任何定义,因为这些实际上只是解决了primops,即硬件处理器指令.