githubModifier

Type Result

Présentation

A.k.a Either (Haskell)

Modélise une double-track Succès/Échec

type Result<'Success, 'Error> =   // ☝ 2 paramètres génériques
    | Ok of 'Success    // Track "Succès" == Happy path
    | Error of 'Error   // Track "Échec"  == Voie de garage

Gestion fonctionnelle des erreurs métier (les erreurs prévisibles)

Module Result

Ne contient que 3 fonctions (en F# 5.0) :

map f option : sert à mapper le résultat

  • ('T -> 'U) -> Result<'T, 'Error> -> Result<'U, 'Error>

mapError f option : sert à mapper l'erreur

  • ('Err1 -> 'Err2) -> Result<'T, 'Err1> -> Result<'T, 'Err2>

bind f option : idem map avec fonction f qui renvoie un Result

  • ('T -> Result<'U, 'Error>) -> Result<'T, 'Error> -> Result<'U, 'Error>

  • 💡 Le résultat est aplati, comme la fonction flatMap sur les arrays JS

  • ⚠️ Même type d'erreur 'Error pour f et le result en entrée

💡 Depuis F# 7.0, le module Result contient plus de fonctions afin d'être aussi fonctionnel que le type Option , avec les correspondances suivantes :

Option
Result
List

Some value

Ok value

[ value ]

None

Error () / Error _

[ ]

isSome / isNone

isOk / isError

× / isEmpty

contains someValue

contains okValue

contains value

count

count

length

defaultValue value defaultWith defThunk

defaultValue value defaultWith defThunk

exists predicate forall predicate

exists predicate forall predicate

exists predicate forall predicate

filter predicate

×

filter predicate

iter action map f / bind f fold f state

iter action map f / bind f fold f state

iter action map f / bind f fold f state

×

mapError f

×

toArray / toList

toArray / toList

×

×

toOption

×

Quiz 🎲

Implémenter Result.map et Result.bind

💡 Tips :

  • Mapping sur la track Succès

  • Accès à la valeur dans la track Succès :

    • Utiliser pattern matching (match result with...)

  • Retour : simple Result, pas un Result<Result> !

Solution

Result : tracks Success/Failure

map : pas de changement de track

bind : routage possible vers track Failure mais jamais l'inverse

☝ Opération de mapping/binding jamais exécutée dans track Failure

Result vs Option

Option peut représenter le résultat d'une opération qui peut échouer ☝ Mais en cas d'échec, l'option ne contient pas l'erreur, juste None

Option<'T>Result<'T, unit>

Exemple :

Modification de la fonction checkAnswer précédente pour indiquer l'erreur :

Result vs Validation

Result est "monadique" : à la 1ère erreur, on "débranche"

Validation est "applicatif" : permet d'accumuler les erreurs

Plus d'info : 🔗 Validation with F# 5 and FsToolkitarrow-up-right, Compositional IT, Dec 2020

Mis à jour