5

Is it possible to define my own ++ operator for a custom data type in Haskell?

I have:

data MyType = MyType [String]

and I would like to define my own concatenation operator as:

instance ? MyType where
    (MyType x) ++ (MyType y) = MyType (x ++ y)

I can't seem to find the name of the instance class anywhere.

3 Answers 3

13

If you don't insist on calling the operator (++),

import Data.Monoid

instance Monoid MyType where
    (MyType x) `mappend` (MyType y) = MyType (x ++ y)
    mempty = MyType []

Then you can use

(<>) :: Monoid m => m -> m -> m

which is an alias for mappend (I thought it was already a type class member, but it isn't :/). Lists hava a Monoid instance where mappend is (++), so that would do what you desire. The Monoid instance also gives you

mconcat :: Monoid m => [m] -> m

which you can use to concatenate a list of MyTypes.

Sign up to request clarification or add additional context in comments.

4 Comments

that's the difference between a pro and a spare time programmer - knowing there is the Monoid typeclass.
Is the <> operator defined the same as the ++ operator for lists?
@WesleyTansey Yes, but I just checked and it seems that is not yet a class member in released GHC versions, so I have to slightly correct my solution.
It's worth noting that if you have an associative (<>) but no mempty, your type is probably a semigroup. Unfortunately Semigroup isn't currently a superclass of Monoid.
4

easiest it would be to do

import Prelude hiding ((++))
import qualified Prelude as P

data MyType = MyType [String]

class PlusAble a where
    infixr 5 ++
    (++) :: a -> a -> a

instance PlusAble MyType where
    (MyType x) ++ (MyType y) = MyType (x P.++ y)

-- EDIT:
instance PlusAble [a] where
    x ++ y = x P.++ y

2 Comments

This solution seems to be giving me issues with causing all other ++ operations to be ambiguous.
i think you have to add an instance for lists too - i added this in the edit
3

(++) operator does not belong to any type class. You can easily check this:

$ ghci
Prelude> :info (++)
(++) :: [a] -> [a] -> [a]   -- Defined in `GHC.Base'
infixr 5 ++

So, it's just simple function defined in GHC.Base module. You can hide it and define your own one:

import Prelude hiding ((++))
import qualified Prelude -- to get hidden (++) as Prelude.(++)

-- your brand new (++)
infixr 5 ++
(MyType x) ++ (MyType y) = MyType (x Prelude.++ y)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.