Haskell trying to make class Matrix show instance

I am a beginner in haskell, please, tell me what I am doing wrong.

    newtype (Matrix a) = Matr [[a]]
    instance Show (Matrix a) where
        show (Matr d) = print d
            where print [] = []
                print (x:xs) = show x ++ "\n" ++ print xs

    No instance for (Show a) arising from a use of `print'
    Possible fix:
    add (Show a) to the context of the instance declaration

Upvotes: 0

Views: 471

Answers (2)

epsilonhalbe
epsilonhalbe

Reputation: 15967

The error message says "you need a Show instance for the element type of your matrix".

Also print is the wrong function to call here - show is equivalent to toString in languages like java - whereas print is an IO-operation that puts a String to stdout, you are using a name that has already a meaning.

newtype Matrix a = Matr [[a]]

instance Show a => Show (Matrix a) where
    show (Matr xx) = showlines xx
      where showlines [] = ""
            showlines (x:xs) = showelems x ++ "\n" ++ showlines xs
            showelems [] = ""
            showelems (x:xs) = show x ++ " " ++ showelems xs

now this showline/showelems pattern is already a common one the functions are unlines and unwords but the elements need to be strings already so

    show (Matr xx) = let strs = map (map show) xx
                     in unlines $ map unwords xx

or a bit terser

    show (Matr xx) = unlines $ map (unwords . map show) xx

here is some example usage of unlines/unwords

$ > ghci
GHCi, version 7.10.3: http://www.haskell.org/ghc/  :? for help
Prelude> putStrLn $ unlines ["a","b"]
a
b

Prelude> putStrLn $ unlines $ map unwords [["a","b"],["c","d"]]
a b
c d

Prelude> putStrLn $ unlines $ map (unwords . map show ) [[1,2],[3,4]]
1 2
3 4

@lisyarus' answer shows a lot more what happens behind the scene - but note the output of that show function is different from mine.

Prelude> import Data.List
Prelude Data.List> putStrLn $ concat . intersperse "\n" . map show $ [[1,2],[3,4]]
[1,2]
[3,4]

Upvotes: 3

lisyarus
lisyarus

Reputation: 15522

print (x:xs) = show x ++ "\n" ++ print xs

Here, x has type [a]. The instance Show [a] needs an instance of Show a. In other words, you have to tell how to show a in order to be able to show [a].

Add a dependency on Show a in your instance declaration:

instance (Show a) => Show (Matrix a) where
    ...

By the way, your code can be written using standard library like this:

show (Matr d) = concat . intersperse "\n" . map show $ d

Note: You need to import Data.List in your matrix module for the intersperse function!

Upvotes: 2

Related Questions