安全地从矩阵中删除一行

时间:2014-06-05 21:42:37

标签: haskell types

我为简单的类型安全线性代数库编写了以下内容

data Natural where
    Zero :: Natural
    Succ :: Natural -> Natural

type One   = Succ Zero
type Two   = Succ One
type Three = Succ Two
type Four  = Succ Three

data Vector n e where
  EmptyVector :: Vector Zero e
  (:>)        :: e -> Vector n e -> Vector (Succ n) e

deriving instance Eq e => Eq (Vector n e)
deriving instance Show e => Show (Vector n e)

infixr :>

data Matrix r c e where
  EmptyMatrix :: Matrix Zero c e
  (:/)        :: Vector c e -> Matrix r c e -> Matrix (Succ r) c e

deriving instance Eq e => Eq (Matrix r c e)
deriving instance Show e => Show (Matrix r c e)

infixr :/

我现在正在尝试实现该功能

dropRow :: Int -> Matrix r c e -> Matrix r c e

但是,当矩阵的返回值具有不同的行数

时,即使我的部分实现也会开始抛出错误
dropRow i m | i <= 0  = m
dropRow _ EmptyMatrix = EmptyMatrix

有没有办法保留我的类型并仍然实现此功能?我该怎么做?

1 个答案:

答案 0 :(得分:2)

如果它应该从矩阵中删除一行,那么你为dropRow给出的类型并没有多大意义。这个似乎更好:

dropRow :: Int -> Matrix (Succ r) c e -> Matrix r c e

考虑到这一点,你真的不能保持矩阵不变的情况,所以让我们改为错误:

dropRow i m | i < 0 = error "invalid row number"

然后0案例相当简单:

dropRow 0 (_ :/ m) = m

n+1情况有点困难,因为不能保证非空矩阵的“尾部”也是非空的,所以我们需要将单个行矩阵的情况从它有两行或更多行的情况:

dropRow i (v :/ EmptyMatrix) = error "invalid row number"
dropRow i (v :/ m@(_ :/ _)) = v :/ dropRow (i-1) m

请注意,dropRow静态无法获取空矩阵。