Search code examples
haskellconcatenationinstance

Haskell Data Type Instance as operator


I have recieved a exercice to learn about data types in haskell and I can't figure out how to solve this one.

They got me a data like : data CatLista a = Nil | Unit a| Conc (CatLista a) (CatLista a) deriving Eq and I need to make the data types become: Nil -> [] , Unit x -> [x] , Conc -> same operator as (++)

So if you run Conc (Unit 9)(Conc (Unit 5) (Unit 3)) == Conc (Conc (Unit 9) (Unit 5))(Conc (Unit 3) Nil) should give true and Conc (Unit 9)(Unit 3) == Conc (Unit 3) (Unit 9) should give false.

I already tried instancing the show class like this:

instance Show a => Show (CatLista a) where
    show a = case a of
        Nil -> []
        Unit x -> "[" ++ show x ++ "]"
        Conc Nil dos -> show dos
        Conc uno Nil -> show uno 
        Conc uno dos -> "[" + show uno ++ "," ++ show dos ++ "]"

I'm quite new to haskell so I may not know some basics, because I can't understand why if I run it (beeing Conc uno dos -> show uno ++ show dos) with the same command as bellow Conc (Unit 9)(Conc (Unit 5) (Unit 3)) == Conc (Conc (Unit 9) (Unit 5))(Conc (Unit 3) Nil) it still returns False even tough they both return the same [9][5][3] with my show instance.

EDIT

Thanks to you I made it, it know returns correctly the values like intended with this code:

toLista :: Eq a => CatLista a -> [a]
toLista Nil = []
toLista (Unit x) = [x]
toLista (Conc a b) 
                    | a == Nil = toLista b 
                    | b == Nil = toLista a
                    | otherwise = (++) (toLista a) (toLista b)

instance (Show a,(Eq a)) => Show (CatLista a) where 
    show a= show (toLista a)

But still I dont know why if I try the same comparation it still returns False, even tough I get returned the same [9,5,3].

This is probably due to my lack of knowledge in Haskell, sorry about that.


Solution

  • Two values are not equivalent if these produce the same String when calling show on these. The (==) :: Eq a => a -> a -> Bool function is implemented by the Eq typeclass. You thus need to implement the instance of Eq for your CatLista yourself.

    The default implementation for Eq, if you use deriving Eq is that two values are the same if they have the same data constructor, and the parameters are elementwise equivalent by calling (==) on these.

    You thus can implement the instance for Eq yourself with:

    data CatLista a = Nil | Unit a| Conc (CatLista a) (CatLista a) -- ← no deriving Eq
    
    instance Eq a => Eq (CatLista a) where
        ca == cb = toLista ca == toLista cb