2015-04-02 12 views
9

In Scalaz ist jede Monad Instanz automatisch eine Instanz von Applicative.Kann ich Klassen automatisch implementieren?

implicit val listInstance = new Monad[List] { 
    def point[A](a: => A) = List(a) 
    def bind[A, B](fa: List[A])(f: A => List[B]) = fa flatMap f 
} 

List(2) <*> List((x: Int) => x + 1) // Works! 

Ein weiteres Beispiel: Arrow ist automatisch ein Profunctor.

Allerdings muss ich in Haskell immer wieder eine Instanz von Applicative für jede Monad bereitstellen.

Ist es möglich, diesen sich wiederholenden Job zu vermeiden?

+0

Nicht im Moment, AFAIK. Sie müssen 'Instanz Applicative M hinzufügen, wobei pure = return; (<*>) = ap'. Ich glaube, ich sah eine Diskussion über das automatische Ablegen von Superklassen, d. H. Implementieren von 'Monad' und' Functor' und das Hinzufügen von 'Applicative' implizit, aber es wurde nicht implementiert (wieder, AFAIK). Vielleicht können Sie Template Haskell schreiben, um die aktuellen Monad-Instanzen zu scannen und Anwendungen automatisch zu generieren. Ich bin mir nicht sicher, ob das möglich ist. – chi

Antwort

2

Es ist derzeit nicht möglich, obwohl es wäre, wenn Sie die vorhandene Bibliothek geändert haben, um dies zu unterstützen. Drehen DefaultSignatures auf würde Sie

class Applicative f where 
    pure :: a -> f a 
    (<*>) :: f (a -> b) -> f a -> f b 

    default pure :: Monad f => a -> f a 
    default (<*>) :: Monad f => f (a -> b) -> f a -> f b 
    pure = return 
    (<*>) = ap 

Dann schreiben, sobald Sie instance Monad M where {- ... -} umgesetzt hatten, ein einfaches instance Applicative M (ohne where oder Methodendefinitionen) würde diese Standardimplementierungen erben. Ich bin mir nicht sicher, warum das nicht gemacht wurde.

3

Das Problem tritt auf, wenn es zwei Orte gibt, von denen die Instanz abgeleitet werden kann. Angenommen, m ist der Typ a b, wobei Arrow a. Dann gibt es eine offensichtliche Instanz von 10 aus dieser Definition. Welche sollte der Compiler verwenden? Es sollte natürlich genauso funktionieren, aber Haskell hat keine Möglichkeit, das zu überprüfen. Indem Haskell uns dazu veranlasst, die Instanzen zu schreiben, zwingt er uns zumindest dazu, über die Konsistenz unserer Definitionen nachzudenken.

Wenn Sie möchten, gibt es die WrappedMonad Klasse in Control.Applicative, die alle offensichtlichen Fällen mit einem newtype Wrapper, aber unter Verwendung von WrapMonad und unwrapMonad die ganze Zeit entweder nicht so attraktiv.

Verwandte Themen