F# Monad 如何修复数据类型

F# Monad how fix datatypes

我正在尝试用 F# 编写一个 Monad,但我无法编译代码并且出现错误 FS0001 错误:此表达式的类型应为 'Result' 但此处的类型为 '(Result<'a> -> Result<'b>) -> Result<'b>'

open System
type Result<'TSuccess> =
     | Success of 'TSuccess
     | Failure

let bind x f = 
    match x with 
    |  Success x -> f (Success x)
    | Failure -> Failure



let stringToInt (s:string) = 
    try
       let result = s |> int
       Success result 
    with 
       |_-> Failure 

let isPositive (i:int)  = 
    if ( i >  0) then  Success i : Result<int>
    else Failure 

let toString (i:int) = 
    try
       let result = i |> string
       Success result
    with
       |_ -> Failure

let bindIsPositive =  bind isPositive : Result<int>

let bindToString = bind toString : Result<string>

let (>>=) x f = bind f x



let strintToIntIsPositiveIntToString s =  stringToInt >>= bindIsPositive >>= bindToString

[<EntryPoint>]
let main argv =
    printfn "10"
    let mys = strintToIntIsPositiveIntToString "9"
    Console.WriteLine mys.ToString
    0 // return an integer exit code 

首先你的bind类型不对:

your version : Result<'a> -> (Result<'a> -> Result<'b>) -> Result<'b>
typical type : Result<'a> -> ('a -> Result<'b>) -> Result<'b>

如果你把参数的顺序调换一下得到:

bind : ('a -> Result<'b>) -> Result<'a> -> Result<'b>

因此,您可以使用以下 bind:

let bind f x = 
    match x with 
    | Success x -> f x
    | Failure -> Failure

执行此操作后,您可以定义 bindIsPositivebindToStringbind 操作现在将一个函数作为第一个参数,所以这可行,但你必须删除你的类型注释:

let bindIsPositive =  bind isPositive 
let bindToString = bind toString

编写函数时,您可以使用 >>= 运算符,或使用普通的 F# 管道和 bind 函数:

let strintToIntIsPositiveIntToString x =  x |> stringToInt |> bindIsPositive |> bindToString
let strintToIntIsPositiveIntToString x =  x >>= stringToInt >>= isPositive >>= toString