方法签名Haskell用户定义的类型

我正在学习Haskell,并最终读到了这个,我试图找出代码的某些部分的作用。

首先,有一个数据类型定义:

infixl 4 :+:
infixl 5 :*:, :/:
infixr 6 :^:

data Expr a = Var Char
             | Const a 
             | (Expr a) :+: (Expr a) 
             | (Expr a) :*: (Expr a)
             | (Expr a) :^: (Expr a)
             | (Expr a) :/: (Expr a)
             deriving (Show, Eq)

接下来有一个功能:

simplify :: (Num a, Eq a, Floating a) => Expr a -> Expr a
simplify (Const a :+: Const b) = Const (a + b)
simplify (a       :+: Const 0) = simplify a
simplify (Const 0 :+: a      ) = simplify a

那么,在这种情况下,“(数字a,公式a,浮动a)=> Expr a”代表什么?

“Expr”不是构造函数,在第一行中,类型是“+(Expr Expr)”,那么“a”在这里意味着什么,为什么它限制为双精度? 在函数第二行中与“a”相关的类型签名是“a”,即使这里显然是Expr?


在数据定义中

data Expr a = ...

a装置,有一个类型变量那里。 一个简单的例子是

data Two a = Two a a

这是一个名为Two的类型,它采用单个类型参数。 它有一个数据构造函数,也叫做Two ,它有两个字段,每个类型都是a 。 例如, Two Int类型具有专门的构造函数Two :: Int -> Int -> Two Int

在这种情况下,你说你的Expr类型有一个类型参数,并且有许多构造函数,其中一些具有类型为a字段。 您可以使用它来获取Expr Int类型的值,例如Const 1 :+: Const 2

当你看到类型签名像

simplify :: (Num a, Eq a, Floating a) => Expr a -> Expr a

这意味着该函数接受Expr a类型的值并返回相同类型的值,除此之外,类型变量a具有其他约束。 即NumEqFloating 。 这些是类型类,并且类型a必须实现这些类型类才能在Expr a上使用simplify

a在类型签名无关与a中定义的第一行simplify 。 这只是作者选择使用相同名称的选择。 类型名称和数据名称在Haskell中完全不同的名称空间中,它们根本没有冲突或关联。


对于每种类型的a具有用于类型类实例NumEqFloatingsimplify可以专注于Expr a -> Expr a 。 类型和值的命名空间是分开的。 Expr是一个类型构造函数。 Expr a是一种Expr a类型。 这里没有任何东西被限制为Double(+)承认一切都是Num实例。

链接地址: http://www.djcxy.com/p/43435.html

上一篇: Method signature Haskell user defined type

下一篇: Type erasure in Haskell?