我想做的是使用中缀 fmap(我将其定义为 <^>)来处理多种类型,例如 Option 和 Either(自定义类型)。
鉴于:
type Either<'a, 'b> = Left of 'a | Right of 'b
在代码中我希望能够做到:
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
其中 (<^>) 为每个:
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
为了让 Option <^> 工作,我扩展了模块:
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 ()
对于任何一个:
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
这几乎可以工作,但是一次只能使用一个。一个 Either 模块也可以附加到 FSharp.Core,但同样你只能拥有一个或另一个。
我知道这可以用 2 种自定义类型来完成,比如 Either 和 Maybe(Haskell 选项),但是我想坚持使用 Option。
欢迎任何和所有建议。