*User> :t sqrt
sqrt :: Floating a => a -> a
我不明白Floating a => a -> a
想告诉我什么。我的教授告诉我sqrt
可以认为是sqrt :: Double -> Double
它的确如此,但Floating a => a -> a
是什么意思?双精度和浮点的含义?
谢谢
*User> :t sqrt
sqrt :: Floating a => a -> a
我不明白Floating a => a -> a
想告诉我什么。我的教授告诉我sqrt
可以认为是sqrt :: Double -> Double
它的确如此,但Floating a => a -> a
是什么意思?双精度和浮点的含义?
谢谢
在ghci
尝试交互一个有用的东西是:info <something>
命令,有时可以告诉你有用的东西。
> :info Floating
class Fractional a => Floating a where
pi :: a
exp :: a -> a
log :: a -> a
sqrt :: a -> a
(**) :: a -> a -> a
---------------------------------------- loads more stuff
-- Defined in ‘GHC.Float’
instance Floating Float -- Defined in ‘GHC.Float’
instance Floating Double -- Defined in ‘GHC.Float’
这是什么意思? Floating
是型号。有多种类型的浮点数。事实上,两个来标准:Float
和Double
,其中Double
给你两倍的精度Float
。 Floating a
中的a
代表任何类型,并且大的操作列表(包括sqrt
)是该类的任何实例必须实现的接口。 sqrt
位于Floating
的接口中这一事实意味着它始终只能用于Floating
的实例。也就是说,你的类型给出你说
sqrt :: Floating a => a -> a
的=>
语法预示着约束,这里Floating a
其左侧。类型说
任何类型
a
这是Floating
一个实例,给a
类型的输入,输出有型a
您可以通过填写a
与任何专门这种类型类型,其约束Floating a
可以得到满足,所以下面都是真
sqrt :: Float -> Float
sqrt :: Double -> Double
现在,Float
和Double
由不同的位模式表示,所以取平方根的计算机制在每种情况下都不相同。不用记得用于不同类型的不同版本的不同名称是很方便的。 “约束”Floating a
确实代表接口中所有操作的类型a
的实现的记录(或字典)。什么sqrt
类型实际上是说是
给出一种类型,
a
和实现所有Floating
操作的字典,我会采取a
,并给您一个a
和它的工作原理通过从字典中提取相关的sqrt
实现并在给定的输入上使用它。
因此,=>
表示带有不可见字典输入的函数类型,就像->
表示具有可见值输入的函数类型一样。当你使用该函数时,你不会(当然,你不能)编写字典:编译器从类型中计算出来。当我们写
sqrt :: Double -> Double
我们指的是一般sqrt
功能无形中应用于Floating Double
字典。
这些函数和常量都在一个名为Floating的类中,这一事实相当令人伤心,尤其是当平方根比一般的求幂非常简单时更是如此。 – dfeuer
你可以把一部分的=>
左侧为一组约束的。
Floating a
表示:类型a
必须是Floating
类型类的实例。我假设你知道什么类型是。如果不是看到this或搜索“Haskell的类型类”
所以:Floating a => a -> a
手段:给定任何类型a
这是Floating
类型的类的实例,这个函数的类型是a -> a
。由于Haskell具有多种类型的浮点数,因此使用“更通用”类型。 Floating
的一个实例确实是Double
。
Floating
是一个类型类。你可以把它看作是数字类型支持以下操作的集合:
sqrt, exp, log, (**)
trig functions: sin, cos, tan, asin, acos, atan, pi
hyperboolic trig functions: sinh, cosh, tanh, asinh, acosh, atanh
如果你知道Java的,那么你可以这样想浮动作为Java的接口类型类。
的这些都是Floating
类类型的实例:
Complex Double
是复数,其中实部和虚数部分用Double
值表示。
类型的示例,其不在Floating
类:
签名sqrt :: Floating a => a -> a
大致翻译为:
对于任何类型一个,如果一个在浮动类,然后开方是利用函数的一个并返回一个
这意味着,你可以写这样的代码:
root a b c = (-b + sqrt (b*b - 4*a*c))/(2*a)
,你可以调用root
与任何Double
,Float
或Complex Double
参数(只要它们都是相同类型)。例如:
import Data.Complex
ghci> let root a b c = (-b + sqrt (b*b - 4*a*c))/(2*a)
ghci> root 1 0 1 :: Double
NaN -- can't represent sqrt -1 as a Double
ghci> root 1 0 1 :: Complex Double
0.0 :+ 1.0 -- sqrt -1 as a Complex number = i
注相同的表达root 1 0 1
如何让基于我们被迫返回类型是不同的结果。
考虑这个问题,而不是:
axe :: Log -> (Log, Log)
其将木原木两个函数。我们可以概括这个吗?事实证明,我们可以:
class Splittable l where
axe :: l -> (l,l)
现在斧头不特定于Log
S,但可以拆分任何足够柔软。
instance Splittable Log where
axe = ... -- previous definition, for logs
instance Splittable Neck where
axe = ... -- executable version
对于sqrt
这是类似的:这个功能肯定是有道理的(积极)Double
S,但它也可以运行在更多的一般类型的数字。例如,
> sqrt (-1) :: Double
NaN -- urgh... negative numbers don't have real roots!
> :m +Data.Complex
> sqrt (-1) :: Complex Double
(- 0.0) :+ 1.0
的Floating a
位是需要的类型a
属于的类的表示,或者是可见的类型的约束,浮点数,即,a
属于Floating
类,或,a
是的一个实例Floating
。
你可以考虑一下类型接口 - 类型a
或者实现了“接口”或者它没有;现在sqrt
只适用于执行Floating
的任何类型a
。
但是不要太过于忽视这种类比 - 它的结束速度几乎和它开始时一样快:Java,接口和Haskell类型之间的差异比它们之间的相似性要多,但类比对于“登上”。
综上所述,Floating a => a -> a
指:从任何类型a
值的函数(即a -> a
),该相同类型的a
值,只要类型a
类似于浮点。
在GHCI REPL做:i Floating
会,除了Floating
型类的结构,显示你实现它的类型的列表:
Prelude> :i Floating
class Fractional a => Floating a where
... LOTS OF FUNCTION DECLARATIONS ...
-- Defined in ‘GHC.Float’
instance Floating Float -- Defined in ‘GHC.Float’
instance Floating Double -- Defined in ‘GHC.Float’
约束都有自己的在Haskell语言并可以组成,所以你可以有(Floating a, Floating c, Foo a, Bar [b], Baz c) => a -> [b] -> (a, c)
或其他一些疯狂的想象型签名。
请问这个问题解决了你的怀疑:https://stackoverflow.com/questions/32974091/what-does-mean-in-a-type-signature/32980202#32980202 – Sibi
程序员可以拥有的最好的教授是程序员他自己:http://learnyouahaskell.com,http://book.realworldhaskell.org/read/提供了一些自学成才和停止依赖教授的资源。 –
@ErikAllik,什么?我认为这位教授有理由进行这种简化。他们不想进入类型类,并且不可能在Haskell中使用数字做很多事情,而不使用碰巧是类多态的函数。 – dfeuer