我为简单的类型安全线性代数库编写了以下内容
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
有没有办法保留我的类型并仍然实现此功能?我该怎么做?
答案 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
静态无法获取空矩阵。