Ce que je voudrais faire est d'utiliser infixe fmap (que j'ai défini comme < ^>) pour travailler pour plusieurs types tels que Option et Sither (personnalisé type).F # Opérateurs infixes communs (fmap, applicative, bind, etc) pour plusieurs types
Étant donné:
type Either<'a, 'b> = Left of 'a | Right of 'b
Dans le code, je voudrais être en mesure de le faire:
let fO (a : int option) = None
let fE (a : Either<string,int>) = Left "dummy"
let mO = Some 1
let mE = Right 1
let testO = f0 <^> m0
let testE = fE <^> mE
Où (< ^>) pour chacun:
let (<^>) f m = match m with | Some a -> Some <| f a | None -> None
let (<^>) f m = match m with | Right a -> Right <| f a | Left a -> Left a
Pour obtenir la Option < ^> pour travailler j'ai prolongé le module:
namespace Microsoft.FSharp.Core
[<AutoOpen>]
module Option =
let (<^>) f m = match m with | Some a -> Some <| f a | None -> None
[<assembly:AutoOpen("Microsoft.FSharp.Core")>]
do()
Et pour un ou l'autre:
type Either<'a, 'b> = Left of 'a | Right of 'b with
static member (<^>) (f,m) = match m with | Right a -> Right <| f a | Left a -> Left a
Cela fonctionne presque, mais un seul peut être utilisé à la fois. Un module Sither peut également être ajouté à FSharp.Core, mais vous ne pouvez en avoir qu'un seul ou l'autre.
Je suis conscient que cela peut être complété avec 2 types personnalisés, disons Soit et Peut-être (option Haskell), je voudrais cependant rester avec Option.
Toutes les suggestions sont les bienvenues.
Je n'ai pas assez d'expérience pour répondre à votre question principale, mais savez-vous de F # 's [de type 'Choice'] (https://msdn.microsoft.com /en-us/visualfsharpdocs/conceptual/core.choice%5B't1,'t2%5D-union-%5Bfsharp%5D)? C'est l'équivalent intégré à 'Sither'. Ou si Left représente un cas "d'échec" et Right représente un cas de "succès", alors l'équivalent F # est le type ['Result'] (https://github.com/fsharp/fslang-design/blob/master/FSharp -4.1/FS-1004-result-type.md), disponible depuis F # 4.1. – rmunn
Vous pouvez jeter un oeil à [F # +] (https://github.com/gusty/FSharpPlus) qui le fait déjà, bien que l'opérateur pour '' fmap'' soit '' << | '' (le même opérateur est utilisé dans FParsec). Vous avez aussi '' bind'' comme '' >> = '' et les applicatifs '' '' et '' <*> ''. Si vous regardez le code source, vous verrez comment il est mis en œuvre, c'est un raffinement de la technique expliquée dans la réponse ci-dessous par @TheInnerLight – Gustavo
@Gustavo Bon point, j'ai ajouté cela à ma réponse. – TheInnerLight