Essayer de composer le non-composable: soulever tout

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 .

Source: https://habr.com/ru/post/fr485518/


All Articles