haskell - 无法在 haskell 中使用 GADT 实现矩阵和向量
问题描述
我是 Haskell 的初学者。我试图在 haskell 中实现矩阵和向量。我希望这些支持 Num 类型类中的所有类型,但不支持其他类型,所以我尝试使用 GADT,但我遇到了错误,你能解释为什么我会遇到错误。或者我可以不用这种方式获得相同的功能。
我的代码:
{-# LANGUAGE GADTs #-}
class LStruct s where
scale :: (Num a) => a -> s -> s
add :: s -> s -> s
data Vector a where
Vector :: (Num a) => a -> Vector [a]
data Matrix a where
Matrix :: (Num a) => a -> Matrix [a]
instance LStruct (Vector a) where
scale a (Vector xs) = Vector (map (*a) xs)
add (Vector xs) (Vector ys) = Vector (zipWith (+) xs ys)
错误:
[-Wdeferred-type-errors]
• Could not deduce: a2 ~ [a1]
from the context: (a ~ [a2], Num a2)
bound by a pattern with constructor:
Vector :: forall a. Num a => a -> Vector [a],
in an equation for ‘scale’
at /home/d4rk0wl/Playground/hs/Mask/.stack-work/intero/intero10129CJD-TEMP.hs:20:12-20
‘a2’ is a rigid type variable bound by
a pattern with constructor:
Vector :: forall a. Num a => a -> Vector [a],
in an equation for ‘scale’
at /home/d4rk0wl/Playground/hs/Mask/.stack-work/intero/intero10129CJD-TEMP.hs:20:12-20
• In the second argument of ‘map’, namely ‘xs’
In the first argument of ‘Vector’, namely ‘(map (* a) xs)’
In the expression: Vector (map (* a) xs)
• Relevant bindings include
xs :: a2
(bound at /home/d4rk0wl/Playground/hs/Mask/.stack-work/intero/intero10129CJD-TEMP.hs:20:19)
a :: a1
(bound at /home/d4rk0wl/Playground/hs/Mask/.stack-work/intero/intero10129CJD-TEMP.hs:20:9)
scale :: a1 -> Vector a -> Vector a
(bound at /home/d4rk0wl/Playground/hs/Mask/.stack-work/intero/intero10129CJD-TEMP.hs:20:3)
[-Wdeferred-type-errors]
• Could not deduce: a2 ~ [c0]
from the context: (a ~ [a1], Num a1)
bound by a pattern with constructor:
Vector :: forall a. Num a => a -> Vector [a],
in an equation for ‘add’
at /home/d4rk0wl/Playground/hs/Mask/.stack-work/intero/intero10129CJD-TEMP.hs:21:8-16
or from: (a ~ [a2], Num a2)
bound by a pattern with constructor:
Vector :: forall a. Num a => a -> Vector [a],
in an equation for ‘add’
at /home/d4rk0wl/Playground/hs/Mask/.stack-work/intero/intero10129CJD- TEMP.hs:21:20-28
‘a2’ is a rigid type variable bound by
a pattern with constructor:
Vector :: forall a. Num a => a -> Vector [a],
in an equation for ‘add’
at /home/d4rk0wl/Playground/hs/Mask/.stack-work/intero/intero10129CJD-TEMP.hs:21:20-28
Expected type: [c0]
Actual type: a1
• In the second argument of ‘zipWith’, namely ‘xs’
In the first argument of ‘Vector’, namely ‘(zipWith (+) xs ys)’
In the expression: Vector (zipWith (+) xs ys)
• Relevant bindings include
ys :: a2
(bound at /home/d4rk0wl/Playground/hs/Mask/.stack-work/intero/intero10129CJD-TEMP.hs:21:27)
解决方案
我想你打算写:
data Vector a where
Vector :: (Num a) => [a] -> Vector a
“可以从 a 的列表构造一个 Vector 或 a ”
您问题中的版本需要一个a
,并且您得到的错误是关于 GHC 试图映射该单个值。
更广泛地说,我建议将Num
约束从构造函数移到使用Vector
. 以这种方式编写的代码似乎可以从 GHC 获得更好的错误消息,并且更易于使用。我不确定这是否有深层原因,或者这只是 GHC 开发人员在哪里花费时间的问题。
所以实例声明可能变成:
instance Num a => LStruct (Vector a) where
并且实例主体可以保持不变。
推荐阅读
- c# - 在 VS2017 中检查与 Package Reference 相关的程序集
- c# - 循环遍历数据表选择数据 C#
- c# - 如何使用 C# 在 Clint Side Table 中删除/添加宽度?
- node.js - fs-stat 赋予价值 - Node.js
- php - 在 localhost 上的 Codeigniter 中实现忘记密码
- python - happybase 1.1.0 api 与 Hbase2.1.2 兼容吗?我遇到运输异常
- firebase - 如何在 Firestore 中为 whereEqualTo 查询计费?
- javascript - 如何在 Twilio 可编程聊天中收听来自多个频道的新消息?
- micronaut - 如何将 Bean 定义为“RestTemplate”?
- wordpress - 如何以折扣 > 2% 展示特价商品