2015-10-07 168 views
0
*User> :t sqrt 
sqrt :: Floating a => a -> a 

我不明白Floating a => a -> a想告诉我什么。我的教授告诉我sqrt可以认为是sqrt :: Double -> Double 它的确如此,但Floating a => a -> a是什么意思?双精度和浮点的含义?

谢谢

+0

请问这个问题解决了你的怀疑:https://stackoverflow.com/questions/32974091/what-does-mean-in-a-type-signature/32980202#32980202 – Sibi

+0

程序员可以拥有的最好的教授是程序员他自己:http://learnyouahaskell.com,http://book.realworldhaskell.org/read/提供了一些自学成才和停止依赖教授的资源。 –

+1

@ErikAllik,什么?我认为这位教授有理由进行这种简化。他们不想进入类型类,并且不可能在Haskell中使用数字做很多事情,而不使用碰巧是类多态的函数。 – dfeuer

回答

5

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型号。有多种类型的浮点数。事实上,两个来标准:FloatDouble,其中Double给你两倍的精度FloatFloating 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 

现在,FloatDouble由不同的位模式表示,所以取平方根的计算机制在每种情况下都不相同。不用记得用于不同类型的不同版本的不同名称是很方便的。 “约束”Floating a确实代表接口中所有操作的类型a的实现的记录(或字典)。什么sqrt类型实际上是说是

给出一种类型,a和实现所有Floating操作的字典,我会采取a,并给您一个a

和它的工作原理通过从字典中提取相关的sqrt实现并在给定的输入上使用它。

因此,=>表示带有不可见字典输入的函数类型,就像->表示具有可见值输入的函数类型一样。当你使用该函数时,你不会(当然,你不能)编写字典:编译器从类型中计算出来。当我们写

sqrt :: Double -> Double 

我们指的是一般sqrt功能无形中应用于Floating Double字典。

+0

这些函数和常量都在一个名为Floating的类中,这一事实相当令人伤心,尤其是当平方根比一般的求幂非常简单时更是如此。 – dfeuer

2

你可以把一部分的=>左侧为一组约束的。

Floating a表示:类型a必须是Floating类型类的实例。我假设你知道什么类型是。如果不是看到this或搜索“Haskell的类型类”

所以:Floating a => a -> a手段:给定任何类型a这是Floating类型的类的实例,这个函数的类型是a -> a。由于Haskell具有多种类型的浮点数,因此使用“更通用”类型。 Floating的一个实例确实是Double

+0

谢谢。因为我们没有指定我们要发送的内容作为输入,所以我们说'a - > a'来简化它,因为有几种类型的浮点数(Double,Float) – Charana

+0

@Charana是真的,但还不够:我们不允许*任何*'a'。我们只允许'a'使得'Floating a'成立,换句话说,只有'a'是'Floating'的实例。 – sinelaw

2

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与任何DoubleFloatComplex 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如何让基于我们被迫返回类型是不同的结果。

2

考虑这个问题,而不是:

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 
2

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)或其他一些疯狂的想象型签名。