让Haskell区分类型同义词

Aus*_*ett 3 haskell types type-alias type-synonyms

我喜欢Haskell类型同义词的概念,因为它们允许区分共享底层表示的抽象数据类型.不幸的是,当我写一个类似的程序

data Vector a = Vec a a

-- Some definitions here about (+) and (*) for Vector ...

type Position = Vector Float
type Velocity = Vector Float
type Time = Float

step :: Position -> Velocity -> Time -> Position
step p v dt = p + v*dt

p :: Position
p = Vec 0.0 0.0

v :: Velocity
v = Vec 1.0 1.0

p' = step v p 0.01
Run Code Online (Sandbox Code Playgroud)

这是完全有效的Haskell代码,尽管v并且p处于错误的位置.我想加强类型同义词之间的区别,这样它们仍然可以共享底层表示,但在函数应用程序中不会被接受.这可能吗?

ber*_*gey 6

newtype很可能是你想要的,或者无论如何,我们得到的最好的.就像type,它为现有类型定义一个新名称,并且运行时表示将是相同的.与type(但是data)不同,它们在类型检查期间被认为是不同的,并且有一个新的数据构造函数.

所以你可能有以下代码:

newtype Position = Position (Vector Float)
p :: Position
p = Position (Vec 0 0)
Run Code Online (Sandbox Code Playgroud)


Aad*_*hah 6

你可以做Vector一个假体类型如下:

data Vector t a = Vec a a

data Pos
data Vel

type Position = Vector Pos Float
type Velocity = Vector Vel Float
Run Code Online (Sandbox Code Playgroud)

现在,您可以定义的情况下,PositionVelocity喜欢你通常会怎么做:

p :: Position
p = Vec 0.0 0.0

v :: Velocity
v = Vec 1.0 1.0
Run Code Online (Sandbox Code Playgroud)

但是,它不允许您互换使用它们:

type Time = Float

step :: Position -> Velocity -> Time -> Position
step p v dt = p + v*dt -- you might have to change this definition

p' = step v p 0.01 -- won't compile
Run Code Online (Sandbox Code Playgroud)

您还可以使用DataKinds和更加精确KindSignatures:

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}

data VectorType = Pos | Vel

data Vector (t :: VectorType) a = Vec a a

type Position = Vector Pos Float
type Velocity = Vector Vel Float
Run Code Online (Sandbox Code Playgroud)

希望有所帮助.

  • 我认为现在更常见的是,类型构造函数具有一个或多个幻像参数,而不是说它是一个幻像类型. (2认同)