2015-09-24 29 views
8

Supponiamo di voler rendere tutti i numeri un'istanza di Monoid. Invece di dover creare un'istanza per ogni Num come questo:Puoi creare un'istanza di una classe non per un tipo ma per un'intera classe in Haskell?

instance Monoid Int where 
    mappend = (+) 
    mempty = 0 

instance Monoid Float where 
    mappend = (+) 
    mempty = 0.0 

-- etc 

C'è qualcosa di simile?

instance Num t => Monoid t where 
    mappend = (+) 
    mempty = 0 

Modifica

Alcuni stanno rispondendo con le estensioni GHC ed avvertimento circa i potenziali problemi; Ho trovato quello informativo, ma penso che resterò con Sum, Product e qualunque cosa faccia lo coerce.

+6

quello che stai cercando è già lì - ma ci sono più di un Monoid possibile per i numeri - ecco perché è lì per 'Sum' e' Product' ([vedi Data.Monoid] (https: //hackage.haskell .org/package/base-4.8.1.0/docs/Data-Monoid.html # t: Monoid)) – Carsten

+1

@Carsten Ora che so di 'Sum', posso farlo:' mconcat ([1,2] :: Sum Int) ', che è bello, ma non posso fare' mconcat ([1,2] :: Sum Float) ', né' mconcat ([1,2] :: Sum Fractional) '. Qual è il modo corretto di usare 'Sum' per' Float's e 'Double's? –

+0

Non ho idea di come sia stato il primo a funzionare - ma 'mconcat ([1,2] :: [Sum Float])' funziona bene per me;) – Carsten

risposta

21

Sto interpretando questo come una domanda su una premessa generale, piuttosto che specificamente su Monoid e Num.

Forse potresti ottenere ciò che hai scritto per funzionare, attivando le estensioni della lingua FlexibleInstances, UndecidableInstances e utilizzando istanze sovrapposte.

Ma probabilmente non vorrebbe: si sembrainstance Num t => Monoid t where ... sta dicendo

"Se t è un'istanza di Num, ecco come fare t un'istanza di Monoid ..."

Sfortunatamente, non è giusto. Che in realtà è dicendo è più simile a

"Ecco come fare t un'istanza di Monoid. In primo luogo, è necessario che t essere un'istanza di Num. Avanti ..."

Quindi, se si scrive un dichiarazione di istanza in questo modo, non puoi scrivere altre dichiarazioni di istanza. (Almeno non senza OverlappingInstances, che avrebbe portato i suoi problemi.)

6

GHC permette la tua definizione con alcune estensioni lingua attivata

{-# LANGUAGE FlexibleInstances, UndecidableInstances #-} 

instance Num t => Monoid t where 
    mappend = (+) 
    mempty = 0 

Questo rende 2 <> 3 risultato 5.

Ma questo si sovrappone con altri Monoid casi, in modo da cercare di valutare "Hello" <> "World" risultati con un errore: Overlapping instances for Monoid [Char]

così, penso che la risposta breve è: no.