在自定义类型上使用show

时间:2015-10-19 21:10:16

标签: haskell

我在打印我制作的自定义矩阵类型的内容时遇到问题。当我试着这样做时告诉我

 Ambiguous occurrence `show'
 It could refer to either `MatrixShow.show',
                          defined at Matrices.hs:6:9
                       or `Prelude.show',
                          imported from `Prelude' at Matrices.hs:1:8-17

这是我要导入的模块:

module Matrix (Matrix(..), fillWith, fromRule, numRows, numColumns, at, mtranspose, mmap) where
newtype Matrix a = Mat ((Int,Int), (Int,Int) -> a)

fillWith :: (Int,Int) -> a -> (Matrix a)
fillWith (n,m) k = Mat ((n,m), (\(_,_) -> k))

fromRule :: (Int,Int) -> ((Int,Int) -> a) -> (Matrix a)
fromRule (n,m) f = Mat ((n,m), f)

numRows :: (Matrix a) -> Int
numRows (Mat ((n,_),_)) = n

numColumns :: (Matrix a) -> Int
numColumns (Mat ((_,m),_)) = m

at :: (Matrix a) -> (Int, Int) -> a
at (Mat ((n,m), f)) (i,j)| (i > 0) && (j > 0) || (i <= n) && (j <= m) = f (i,j)

mtranspose :: (Matrix a) -> (Matrix a)
mtranspose (Mat ((n,m),f)) = (Mat ((m,n),\(j,i) -> f (i,j)))

mmap :: (a -> b) -> (Matrix a) -> (Matrix b)
mmap h (Mat ((n,m),f)) = (Mat ((n,m), h.f))

这是我的模块:

module MatrixShow where
    import Matrix


    instance (Show a) => Show (Matrix a) where 
    show (Mat ((x,y),f)) = show f

还有一些地方我可以自己解决这个问题,一些链接有说明或一些教程或其他东西来学习如何做到这一点。

2 个答案:

答案 0 :(得分:4)

问题出在你的缩进上。 show的定义需要相对于instance show a => Show (Matrix a)缩进。事实上,您似乎正在尝试定义一个名为show的新函数,该函数与Show类无关,您无法做到。

答案 1 :(得分:2)

@dfeuer,我的名字仍然有拼写问题,给了你直接的答案--Haskell对布局很敏感 - 但我会试着帮你解决你提到的基本问题评论,没有给你完整的答案。

您提到您对矩阵的表示方式感到困惑。 Read the source, Luke

newtype Matrix a = Mat ((Int,Int), (Int,Int) -> a)

newtype声明会告诉您Matrix是由一对((Int,Int), (Int,Int) -> a)组成的。如果你拆分元组,那就是(Int, Int)对和类型为(Int, Int) -> a的函数(一个带有两个整数参数的函数,它返回任意类型的a)。这告诉我,元组的第一部分代表矩阵的 size ,第二部分是将坐标映射到元素的函数。您的教授给您的一些示例代码似乎证实了这一假设 - 例如,查看atmtranspose

所以,问题是 - 给定矩阵的宽度和高度,以及给出给定坐标元素的函数,我们如何给出显示矩阵中项目的字符串?

我们需要做的第一件事就是枚举矩阵给定宽度和高度的所有可能坐标。 Haskell为这种操作提供了一些有用的语法结构 - 我们可以编写[x .. y]来枚举xy之间的所有值,并使用列表推导来解压缩嵌套中的这些枚举循环。

coords :: (Int, Int)  -- (width, height)
          -> [(Int, Int)]  -- (x, y) pairs
coords (w, h) = [(x, y) | x <- [0 .. w], y <- [0 .. h]]

例如:

ghci> coords (2, 4)
[(0,0),(0,1),(0,2),(0,3),(0,4),(1,0),(1,1),(1,2),(1,3),(1,4),(2,0),(2,1),(2,2),(2,3),(2,4)]

现在我们已经研究了如何列出矩阵中所有可能的坐标,我们如何将坐标转换为a类型的元素?好吧,Mat构造函数包含一个函数(Int, Int) -> a,它为您提供与单个坐标关联的元素。我们需要将该函数应用于我们刚刚枚举的列表中的每个坐标。这就是map的作用。

elems :: Matrix a -> [a]
elems (Mat (size, f)) = map f $ coords size

所以,有代码来枚举矩阵的元素。你能弄清楚如何修改这段代码,以便a)它将元素显示为字符串,b)它是否以逐行的方式显示它们?您可能需要调整这两个功能。

我认为我想提出的更广泛的观点是,尽管感觉你的教授已经把你推到了深处,但总是可以做一些侦探工作并自己弄清楚什么意思。很多 - 最多? - 在本网站上回答问题的人都是自学成才的程序员,包括我自己。我们坚持了下来!

毕竟,这只是代码。如果计算机要理解它,那么它必须写在页面上,这意味着你也可以理解它。