Stephane Rolland
Stephane Rolland

Reputation: 39916

Multiple declarations of 'MyModule.myTypeclassFunction'

in Main.hs

class A aable where
    getName :: aable → String

class B bable where
    getName :: bable → String

returns this compilation error with Leksah/ghc

src\Main.hs:23:4:
    Multiple declarations of `Main.getName'
    Declared at: src\Main.hs:20:4
                 src\Main.hs:23:4

I need both to be able to return a name, with a different signification in both cases. Should I declare class A and B in two different modules ?

Upvotes: 1

Views: 745

Answers (2)

Dan Burton
Dan Burton

Reputation: 53705

When you have different data types that behave differently, but somewhat the same (as in, have the same methods but differing implementations), then it's Haskell classes to the rescue!

data A = A { nameA :: String } deriving (Show, Eq)
data B = B { nameB :: String } deriving (Show, Eq)

class Named a where
    getName :: a -> String

instance Named A where
    getName = nameA

instance Named B where
    getName = nameB

ghci> getName $ A "foo"
"foo"
ghci> getName $ B "bar"
"bar"

(If you haven't seen record syntax yet, there's a good explanation at LYAH)

You can even be more general than that.

{-# LANGUAGE FlexibleInstances, UndecidableInstances, OverlappingInstances #-}
-- The above line should be at the top of your file

-- add this to the file too (anywhere)
instance (Show a) => Named a where
    getName = show

ghci> getName 3
"3"
ghci> show 3
"3"
ghci> getName $ A "foo"
"foo"
ghci> show $ A "foo"
"A {nameA = \"foo\"}"

The OverlappingInstances language pragma is only necessary in this example if you keep both the Instance (Show a) => Named a and the instance Named A, since I made A an instance of Show by deriving it. Use language pragmas with caution and wisdom.

I made A and B data for illustrative purposes, but the (Show a) instance illustrates how this could also be done just as easily for classes.

Upvotes: 3

user395760
user395760

Reputation:

Kneejerk reaction: Use Show. Reading better, I see that what you want is propably different semantically (despite identical type signatures). Why not use a different name? descriptionA and descriptionB perhaps? Declaring them in different modules would solve the compilation error, but (1) you still have two different things with the same name and (2) whenever you import both modules (unqualified), you'll get the same error.

Upvotes: 3

Related Questions