Argus
Argus

Reputation: 911

Using show on a custom type

I'm having trouble printing contents of a custom matrix type I made. When I try to do it tells me

 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

Here is the module I'm importing:

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))

This is my module:

module MatrixShow where
    import Matrix


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

Also is there some place where I can figure this out on my own, some link with instructions or some tutorial or something to learn how to do this.

Upvotes: 0

Views: 413

Answers (2)

Benjamin Hodgson
Benjamin Hodgson

Reputation: 44603

@dfeuer, whose name I continue to have trouble spelling, has given you the direct answer - Haskell is sensitive to layout - but I'm going to try to help you with the underlying question that you've alluded to in the comments, without giving you the full answer.

You mentioned that you were confused about how matrices are represented. Read the source, Luke:

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

This newtype declaration tells you that a Matrix is formed from a pair ((Int,Int), (Int,Int) -> a). If you split up the tuple, that's an (Int, Int) pair and a function of type (Int, Int) -> a (a function with two integer arguments which returns something of arbitrary type a). This suggests to me that the first part of the tuple represents the size of the matrix, and the second part is a function mapping coordinates onto elements. This hypothesis seems to be confirmed by some of the example code your professor has given you - have a look at at or mtranspose, for example.

So, the question is - given the width and height of the matrix, and a function which will give you the element at a given coordinate, how do we give a string showing the items in the matrix?

The first thing we need to do is enumerate all the possible coordinates for the given width and height of the matrix. Haskell provides some useful syntactic constructs for this sort of operation - we can write [x .. y] to enumerate all the values between x and y, and use a list comprehension to unpack those enumerations in a nested loop.

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

For example:

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)]

Now that we've worked out how to list all the possible coordinates in a matrix, how do we turn coordinates into elements of type a? Well, the Mat constructor contains a function (Int, Int) -> a which gives you the element associated with a single coordinate. We need to apply that function to each of the coordinates in the list which we just enumerated. This is what map does.

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

So, there's the code to enumerate the elements of a matrix. Can you figure out how to modify this code so that a) it shows the elements as a string and b) it shows them in a row-by-row fashion? You'll probably need to adjust both of these functions.


I suppose the broader point I'd like to make is that even though it feels like your professor has thrown you into the deep end, it's always possible to do a little detective work and figure out for yourself what something means. Many - most? - of the people answering questions on this site are self-taught programmers, myself included. We persevered!

After all, it's just code. If a computer's going to understand it then it must be written down on the page, and that means that you can understand it, too.

Upvotes: 2

dfeuer
dfeuer

Reputation: 48580

The problem is with your indentation. The definition of show needs to be indented relative to the instance show a => Show (Matrix a). As it is, it appears that you are trying to define a new function called show, unrelated to the Show class, which you can't do.

Upvotes: 4

Related Questions