Il est recommandé de lire le
premier article si vous ne l'avez pas déjà fait. Cet article sera plus court, moins axé sur les détails et davantage sur les capacités.
Selon
Stephen Diel , avec des types dépendants, une compilation plus rapide et un seuil d'entrée plus bas; Les effets algébriques sont l'une des tâches les plus importantes qui seront résolues à l'avenir pour Haskell.
L'avenir n'est pas loin, vous devez donc commencer dès maintenant.
Augmenter les effets vers d'autres effets
class Liftable eff schema where lift :: eff ~> schema
Que signifie essentiellement "uplift"?
l'ascenseur est le même
pur /
retour à l'exception que l'on ne plonge pas la valeur dans l'effet, mais l'effet dans une sorte de transformateur (dans notre cas, dans le circuit du transformateur):
pure :: a -> ta lift :: ua -> tua
Cela nous permet d'utiliser tous les effets à l'intérieur d'un transformateur spécifique - il est facile d'introduire de nouveaux effets, mais plus tard, nous devrons interpréter chacun d'eux.
Ainsi, nous pouvons composer en toute sécurité les effets surélevés:
let f = lift get :: Configured _ t => t _ let g = lift Nothing :: Optional t => t _ let h = lift (failure _) :: Failable _ t => t _ let x = f *> g *> h :: (Applicative t, Configured _ t, Optional t, Failable _ t) => t _
Et soumettez-les dans n'importe quel ordre qui nous convient:
let y = pure _ :: Reader _ :> State _ :> Either _ :> Maybe := Int let z = pure _ :: State _ :> Either _ :> Maybe _ :> Reader := _ let x = f *> g *> h :: (Applicative t, Configured _ t, Optional t, Failable _ t) => t _ let xy = x *> y :: Reader _ :> State _ :> Either _ :> Maybe := _ let xz = x *> z :: State _ :> Either _ :> Maybe _ :> Reader := _
Adapter certains effets à d'autres
class Adaptable subeff eff | subeff -> eff where adapt :: subeff ~> eff
L'adaptation signifie que certains effets peuvent être remplacés par des effets plus puissants. Par exemple, les effets de
Reader et
Writer peuvent être utilisés dans
State , car
State peut lire et écrire, et donc modifier la valeur stockée:
lift put :: Accumulated _ t => t _ lift get :: Configured _ t => t _ (lift . adapt $ put) :: Stateful _ t => t _ (lift . adapt $ get) :: Stateful _ t => t _
Comment est-ce possible? Dans l'article précédent, nous avons divisé l'
État en deux effets:
State s = (->) s :. (,) s
Dans le cas de
Reader , nous élevons simplement le foncteur flèche au niveau
État , et dans le cas de
Writer , le foncteur tuple:
Reader s = (->) s Writer s = (,) s
Nous pouvons adapter
Failable à
Facultatif , mais nous perdrons les informations d'erreur:
(lift $ Just _) :: Optional t => t _ (lift $ failure _) :: Failable _ t => t _ (lift . adapt $ failure _) :: Optional t => t _
Exécuter des effets dans les transformateurs
Pour interpréter un effet dans un transformateur, une méthode d'
exécution suffit:
let xy = x *> y :: Reader _ :> State _ :> Either _ :> Maybe := _ let xy' = run xy _ :: State _ :> Either _ :> Maybe := _ let xy'' = run xy' _ :: Either _ :> Maybe := _ let xy''' = run xy'' :: Maybe (Either _) _
Conclusion et exemples
Donc, en ce moment, sans monades libres / libres (et parfois même sans monades), en utilisant
joint, vous pouvez taper vos expressions en fonction des effets qu'elles produisent. Tout ce dont vous avez besoin est une composition de foncteurs.
Il y a également une
présentation d'un rapport sur ce sujet lors du
rassemblement local à Rostov-sur-le-Don, qui peut être consultée dans un navigateur.
Les meilleurs exemples sont ceux qui se rapprochent le plus possible de la réalité. J'adore la musique, vous pouvez donc voir comment ce système d'effets est utilisé dans un
programme qui télécharge des albums depuis Bandcamp .