2017-06-22 5 views
6

Warum ist guard basierend auf Alternative?Warum basiert `guard` auf` Alternative`?

guard :: Alternative f => Bool -> f() 
-- guard b is pure() if b is True, 
-- and empty if b is False. 

Ich frage, weil guard nur die empty von Alternative verwendet. Es verwendet <|> von Alternative überhaupt nicht. Also warum sollte man zuerst Alternative benutzen?

Ich denke, das liegt daran, dass es eine unausgesprochene Idee hinter Alternative ‚s ist empty die perfekt mit dem, was wir versuchen, mit guard (Stop auf False, weiter auf True) zu erreichen. Wenn dies der Fall ist, bitte erleuchte mich über diese unausgesprochene Idee.

Aber zur gleichen Zeit, wenn fühlt, dass wir einfach ignorieren <|>. Es fühlt sich fast so an, als ob guard nicht "vollständig erfasst" worum es bei Alternative geht. Ich hoffe das ergibt Sinn. Um es konkreter zu machen: Warum erfanden sie nicht eine andere Typklasse namens Stoppable (oder Abortable) und verwendeten diese anstelle von Alternative?

+2

Sie brauchen auch 'pure'. Sicher, du könntest eine 'Pure' Klasse haben, die' pure' anbietet, und eine 'Empty' Klasse, die' empty' liefert und 'Alternative' benötigt beide. Aus pragmatischen Gründen wird jedoch eine Klasse nicht immer in Klassen mit einer einzigen Methode aufgeteilt. – chi

+1

Pragmatische oder historische Gründe in diesem Fall? – gallais

+1

Ich denke es liegt daran, dass es keine Typen gibt, die 'empty' implementieren können und' (<|>) '' nicht implementieren können. Also, theoretisch ist eine Typklasse "Stoppable" gleich "Alternative" (Satz von Typen wird gleich sein). – freestyle

Antwort

8

TL; DR: Historische Gründe. Es wurde dies in MonadPlus vorgesehen, das später seine Applicative Variante Alternative erhielt, und niemand hat vorgeschlagen, Alternative in AZero und AChoice oder ähnlich zu teilen.


Alternative ist eine relativ neue Idee, wie Applicative. Damals, als guard zum ersten Mal ins Auge gefasst wurde, basierte es auf MonadPlus, einem Monad, der Auswahl und Ausfall unterstützen sollte, genau wie Alternative. Sein ursprünglicher Typ war so

guard :: MonadPlus m => Bool -> m() 

, die in der Haskell 98 Bericht angegeben wurden, wo MonadPlus wurde bereits erwähnt. Haskell 1.0 hat übrigens überhaupt keine Monaden benutzt. Wenn Applicative schließlich eine Oberklasse von Monad, Alternative bekam bekam eine Oberklasse von MonadPlus und mzero = empty und mplus = (<|>).

Nun, jetzt wissen wir, warum guardAlternative verwendet. Weil es vorher auf MonadPlus basierte. Warum ist MonadPlus so definiert?

Man müßte eine Mail an SPJ oder jemanden anderen aus dem Komitee schreiben ihre Begründung bekommen von 1998, denn nur ein Jahr später, Erik Meijer and Graham Hutton wrote their "Monadic Parsing in Haskell" Papier. Wenn Sie einen Blick auf dem Papier haben, werden Sie feststellen, dass ihreMonadPlus wie Sie arbeiten beabsichtigen:

class Monad m => MonadZero m where 
    zero :: m a 

class MonadZero m => MonadPlus m where 
    (++) :: m a -> m a -> m a 

So ist es durchaus möglich, diese „arretierbar“ die Art und Weise zu handhaben Sie haben beschrieb es. Es gibt jedoch einfach keine Klasse base, die derzeit empty ohne Alternative definiert. Es könnte einen geben, aber es wurde noch nicht vorgeschlagen.

Beachten Sie, dass dies ein wiederkehrendes Thema mit Haskell-Klassen ist. Monoid enthält mappend und mempty. Nach seiner Konzeption bemerkte jemand, dass es bestimmte Arten gibt, bei denen mappend Sinn macht, aber nicht mempty. Hier zum Beispiel

newtype Min a = Min a 

combine :: Ord a => Min a -> Min a -> Min a 
combine (Min x) (Min y) = Min (min x y) 

ist mappend = combine klar assoziativ, während ein leeres Min nicht möglich ist, wenn wir nur Ord verwenden, würden wir Bounded verwenden. Deshalb gibt es jetzt Semigroup, was noch keine Basisklasse von Monoid ist, aber uns diese assoziative Operation gibt.

Um wieder auf Ihre ursprüngliche Frage zu kommen: guardAlternative verwendet, weil Alternativeempty bietet, und empty "hält" die Auswertung in bestimmten Alternative ‚s. Es gibt keine andere Klasse, die das enthält, noch.

Aber mit einem Vorschlag, könnte es irgendwann sein, obwohl ich nicht sicher bin, was die Meinung der Gemeinschaft zum Teilen Alternative ist.

By the way, Sprachen wie PURESCRIPT gespalten Alternative, obwohl sie es umgekehrt aufgeteilt ...

Weitere Informationen zu Alternative und warum ich Monoid als ein weiteres Beispiel verwendet, Confused by the meaning of the 'Alternative' type class and its relationship to other type classes sehen.

+1

Ich würde nicht sagen, dass es ein Versehen ist, per se. Es gibt einen legitimen Design-Kompromiss zwischen Granularität und Kohäsion. Ich persönlich bevorzuge die Haskell-Klassenhierarchie gegenüber der PureScript-Hierarchie. 'empty' und' <|> '" gehen zusammen "auf natürliche Weise. –

+1

@ BenjaminHodgson Ich entfernte das Urteil, es war nicht wirklich angemessen. – Zeta

+1

Es lohnt sich auch, an 'MonadFail' zu denken, dessen' fail' eine Art "leer" ist, die aber die Leere mit '>> =' anstatt einer Wiederherstellung erweitert. – dfeuer