2012-11-27 24 views
5

Ist es möglich, meinen eigenen ++ Operator für einen benutzerdefinierten Datentyp in Haskell zu definieren?Benutzerdefinierter Concat (++) Operator in Haskell

ich habe:

data MyType = MyType [String] 

, und ich möchte meine eigene Verkettungsoperator definieren:

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

ich überall den Namen der Instanz der Klasse zu finden scheinen nicht.

Antwort

13

zu tun, wenn Sie den Betreiber nicht darauf bestehen, (++) auf Aufruf,

import Data.Monoid 

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

Dann können Sie

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

verwenden, die einen ist Alias ​​für mappend (Ich dachte, es war schon ein Typ Klassenmitglied, aber es ist nicht : /). Listen hava a Monoid Instanz wo mappend ist (++), so würde das tun, was Sie wünschen. Die Monoid Instanz gibt Ihnen auch

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

, die eine Liste von MyType s verketten können.

+0

das ist der Unterschied zwischen einem Pro und einem Freizeit Programmierer - zu wissen, dass es die 'Monoid' typeclass ist. – epsilonhalbe

+0

Ist der Operator <> genauso definiert wie der Operator ++ für Listen? –

+0

@WesleyTansey Ja, aber ich habe gerade überprüft und es scheint, dass noch kein Klassenmitglied in freigegebenen GHC-Versionen ist, also muss ich meine Lösung leicht korrigieren. –

4

am einfachsten wäre es

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 
+0

Diese Lösung scheint zu sein gibt mir Probleme mit verursacht alle anderen ++ Operationen sein zweideutig: Sie können es Ihr eigenes verstecken und definieren. –

+0

ich denke, dass Sie eine Instanz für Listen hinzufügen müssen - ich habe dies in der Bearbeitung hinzugefügt – epsilonhalbe

3

(++) Der Operator gehört keiner Klasse an. Sie können dies leicht überprüfen:

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

Also, es ist nur eine einfache Funktion in GHC.Base Modul definiert.

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

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