Haskell 中的矩阵构造函数和方法
所以这里是一个嵌套列表 [[1, 2], [3, 4]]
类 Eq、Num 和 Show 的实例
我想将它包装在一个名为 Matrix 的类型中,并使其成为我已经创建的 (添加、sub、mul)嵌套列表(矩阵)的运算。如何重载 (+ - *) 运算符,以便 + 映射到 add,- 映射到 sub,* 映射到 mul?所以我可以做到这一点
> ma = Matrix [[1, 2], [3, 4]]
> mb = Matrix [[5, 6], [7, 8]]
> ma + mb
> ma - mb
> ma * mb
谢谢
编辑
这是我迄今为止的尝试
> add = zipWith (zipWith (+)) > sub = zipWith (zipWith (-)) > data Matrix a = Matrix [[a]] deriving (Eq, Show) > instance Num (Matrix a) > where > (+) x y = Matrix $ add x y > (-) x y = Matrix $ sub x y
得到的
Couldn't match expected type `[[c0]]' with actual type `Matrix a' In the first argument of `sub', namely `x' In the second argument of `($)', namely `sub x y' In the expression: Matrix $ sub x y
这是我从 ghci编辑#2 我现在需要弄清楚的最后一件事是
如何打印
1 2 3 4
而不是 Matrix [[1,2],[3,4]]
So here is a nested list [[1, 2], [3, 4]]
I want to wrap it in a type called Matrix, and make it an instance of the classes Eq, Num, and Show
I have already created (add, sub, mul) operations for nested lists (matrices). How do I overload (+ - *) operators so that + maps to add, - maps to sub, and * maps to mul? So I can do this
> ma = Matrix [[1, 2], [3, 4]]
> mb = Matrix [[5, 6], [7, 8]]
> ma + mb
> ma - mb
> ma * mb
Thanks
EDIT
this is my attempt so far
> add = zipWith (zipWith (+)) > sub = zipWith (zipWith (-)) > data Matrix a = Matrix [[a]] deriving (Eq, Show) > instance Num (Matrix a) > where > (+) x y = Matrix $ add x y > (-) x y = Matrix $ sub x y
This is what I get from ghci
Couldn't match expected type `[[c0]]' with actual type `Matrix a' In the first argument of `sub', namely `x' In the second argument of `($)', namely `sub x y' In the expression: Matrix $ sub x y
EDIT #2
The last thing I need to figure out right now is
how to I print
1 2 3 4
Instead of Matrix [[1,2],[3,4]]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您在为您的类型定义
Num
实例时遇到问题吗?尝试以下代码:测试:
其余类方法的定义留作练习。
这是
Matrix
的Show
实例:测试:
Are you having a problem with defining a
Num
instance for your type? Try this code:Testing:
Definitions of the remaining class methods are left as exercise.
And here's a
Show
instance forMatrix
:Testing:
如果您检查
add
和sub
的类型,您将看到该问题。Mikhail 的建议是从本质上解开 2D 列表并在 Num 实例方法中重新包装它。另一种方法是修改
add
和sub
方法来处理矩阵。在这里,我使用“提升”方法,编写组合器将函数从一种类型“提升”到另一种类型。使用这些组合器,定义
add
和sub
只需适当提升即可。现在我们有了适用于矩阵的函数,Num 实例很简单
当然我们可以将 lift2dOp 和 liftMatrixOp 组合成一个方便的函数:
现在您尝试:定义
liftMatrix :: (a -> a) ->;矩阵a->矩阵 a
,一元函数的提升函数。现在用它来定义negate
、abs
和signum
。文档建议abs x * signum x
应始终等于x
。看看我们的实现是否如此。事实上,如果您使用更宽松的类型签名编写 liftMatrix,它可以用于为矩阵定义一个 Functor 实例。
现在考虑一下如何实现
fromInteger
。实现这个可以让你在 ghci 中做这样的事情:无论如何,这就是我实现它的方式。请记住,Haskell 代码中的任何数字文字
n
实际上都会转换为fromInteger n
,这就是它起作用的原因。我认为现在这已经足够有趣了,但是如果您需要更多练习,请尝试熟悉这个矩阵的
Arbitrary
实例:If you inspect the type of your
add
andsub
, you will see the issue.Mikhail's suggestion was to essentially unwrap the 2D list and rewrap it in the Num instance methods. Another way to do this is to modify your
add
andsub
methods to work on Matrices instead. Here I use a "lifting" approach, where I write combinators to "lift" a function from one type to another.With these combinators, defining
add
andsub
is simply a matter of lifting appropriately.Now that we have functions that work on Matrices, the Num instance is simple
Of course we could have combined
lift2dOp
andliftMatrixOp
into one convenience function:Now you try: define
liftMatrix :: (a -> a) -> Matrix a -> Matrix a
, a lifting function for unary functions. Now use that to definenegate
,abs
, andsignum
. The docs suggest thatabs x * signum x
should always be equivalent tox
. See if this is true for our implementation.In fact, if you write
liftMatrix
with the more lenient type signature, it can be used to define aFunctor
instance for Matrices.Now think about how you could implement
fromInteger
. Implementing this allows you to do stuff like this in ghci:That's how it works the way I implemented it, anyways. Remember that any numeric literal
n
in Haskell code is actually transformed intofromInteger n
, which is why this works.I think that's enough fun for now, but if you need more exercises, try getting comfortable with this
Arbitrary
instance of Matrices: