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)

  • Permet de limiter usage des exceptions aux erreurs exceptionnelles

  • Dès qu'une opération échoue, les opérations restantes ne sont pas lancées

  • Railway-oriented programming, F# for Fun and Profit

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>

  • Some xOk x

  • NoneError ()

  • Cf. fonctions Option.toResult et Option.toResultWith error de FSharpPlus

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 FsToolkit, Compositional IT, Dec 2020

Mis à jour

Ce contenu vous a-t-il été utile ?