Method signature Haskell user defined type
I'm trying learning Haskell and I ended up reading this and I'm trying to figure out what some parts of the code do.
At first, there's a data type definition:
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)
and next there is a function:
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
So, what does "(Num a, Eq a, Floating a) => Expr a" stand for in this case?
"Expr" is not a constructor, and in the first line the type is "+ (Expr Expr)", so what does "a" mean here, and why is it restricted to be a double? And is the "a" in the type signature related to the "a" in the second line of the function, even if here a is clearly an Expr?
In the data definition
data Expr a = ...
The a
means that there is a type variable there. A simple example would be
data Two a = Two a a
This is a type with the name Two
, which takes a single type parameter. It has a data constructor also called Two
which has two fields, each of type a
. For example, the type Two Int
has the specialized constructor Two :: Int -> Int -> Two Int
In this case, you're saying that your Expr
type has a type parameter, and has a number of constructors, some of which have fields of type a
. You might use this to have a value of type Expr Int
, such as Const 1 :+: Const 2
.
When you see a type signature like
simplify :: (Num a, Eq a, Floating a) => Expr a -> Expr a
This means that the function takes a value of type Expr a
and returns a value of the same type, except here the type variable a
has additional constraints. Namely Num
, Eq
, and Floating
. These are typeclasses, and a type a
must implement those type classes for you to be able to use simplify
on Expr a
.
The a
in the type signature has nothing to do with the a
in the first line of the definition of simplify
. It's just a choice by the author to use the same name. Type names and data names live in completely different namespaces in Haskell, they don't conflict or relate at all.
For each type a
that has instances for the typeclasses Num
, Eq
and Floating
, simplify
can specialize to Expr a -> Expr a
. The namespaces of types and values are separate. Expr
is a type constructor. Expr a
is a type that has values. Nothing here is restricted to be a Double
, (+)
admits everything with a Num
instance.
上一篇: 无法与实际类型'a'匹配预期类型'b'
下一篇: 方法签名Haskell用户定义的类型