Frage

Nach der Typeclassopedia (neben anderen Quellen), Applicative logisch gehört zwischen Monad und Pointed (und damit Functor) in der Art Klassenhierarchie, so dass wir im Idealfall etwas davon haben, wenn der Haskell Auftakt heute geschrieben wurde:

class Functor f where
    fmap :: (a -> b) -> f a -> f b

class Functor f => Pointed f where
    pure :: a -> f a

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

class Applicative m => Monad m where
    -- either the traditional bind operation
    (>>=) :: (m a) -> (a -> m b) -> m b
    -- or the join operation, which together with fmap is enough
    join :: m (m a) -> m a
    -- or both with mutual default definitions
    f >>= x = join ((fmap f) x)
    join x = x >>= id
    -- with return replaced by the inherited pure
    -- ignoring fail for the purposes of discussion

(Wo diese Standarddefinitionen wurden von mir neu eingegeben von der Erklärung bei Wikipedia , wobei Fehler meine eigenen, aber wenn es Fehler gibt, ist es zumindest prinzipiell möglich.)

Da die Bibliotheken derzeit definiert sind, haben wir:

liftA :: (Applicative f) => (a -> b) -> f a -> f b
liftM ::       (Monad m) => (a -> b) -> m a -> m b

und

(<*>) :: (Applicative f) => f (a -> b) -> f a -> f b
ap    ::       (Monad m) => m (a -> b) -> m a -> m b

Beachten Sie die Ähnlichkeit zwischen diesen Arten in jedem Paar.

Meine Frage ist: ist liftM (im Unterschied zu liftA) und ap (im Unterschied zu <*>), einfach ein Ergebnis der historischen Realität, dass Monad nicht mit Pointed und Applicative konzipiert wurde? Oder sind sie in irgendeiner anderen Art und Weise Verhaltens (möglicherweise für einige rechtliche Monad Definitionen) unterscheiden sich von den Versionen, die nur einen Applicative Kontext erfordern?

Wenn sie verschieden sind, könnten Sie einen einfachen Satz von Definitionen zur Verfügung stellen (die Gesetze zu gehorchen erforderlich von Monad, Applicative, Pointed und Functor Definitionen in der Typeclassopedia beschrieben und an anderer Stelle aber nicht vom Typ System erzwungen), für die liftA und liftM anders verhalten?

Alternativ kann, wenn sie nicht eindeutig sind, können Sie beweisen ihre Gleichwertigkeit die gleichen Gesetze wie Räumlichkeiten mit?

War es hilfreich?

Lösung

liftA, liftM, fmap und . sollte alle die gleiche Funktion sein, und sie muss , wenn sie das Funktors Gesetz erfüllen:

fmap id = id

Dies ist jedoch nicht geprüft von Haskell.

Jetzt für Applicative. Es ist möglich, für ap und <*> für einige functors einfach verschieden zu sein, weil es mehr als eine Implementierung sein könnten, die die Typen und die Gesetze erfüllen. Zum Beispiel hat Liste mehr als eine mögliche Applicative Instanz. Sie könnten eine applicative erklären, wie folgt:

instance Applicative [] where
  (f:fs) <*> (x:xs) = f x : fs <*> xs
  _      <*> _      = []
  pure              = repeat

Die ap Funktion würde immer noch als liftM2 id definiert werden, die die Applicative Instanz ist, die mit jedem Monad kostenlos kommt. Aber hier haben Sie ein Beispiel für einen Typkonstruktor mehr als eine Applicative Instanz, die beide von denen die Gesetze erfüllen. Aber wenn Ihr Monaden und Ihre applicative functors nicht einverstanden ist, ist es zum guten Ton für sie verschiedene Typen haben. Zum Beispiel ist das Applicative Beispiel oben nicht mit der Monade für [] einverstanden ist, so sollten Sie wirklich newtype ZipList a = ZipList [a] sagen und dann die neue Instanz für ZipList statt [] machen.

Andere Tipps

Sie können unterscheiden, aber sie sollte nicht .

können Sie unterscheiden, da sie unterschiedliche Implementierungen haben kann: Die eine ist in einem instance Applicative definiert, während die andere in einem instance Monad definiert ist. Aber wenn sie in die Tat unterschiedlich ist, dann würde ich die Programmierer sagt, wer diese Instanzen schrieb schrieben Code irreführend.

Sie haben Recht: Die Funktionen existieren, wie sie aus historischen Gründen tun. Die Menschen haben starke Ideen darüber, wie die Dinge gewesen sein sollte.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top