F#Monad如何修复数据类型

Wal*_*lly 3 monads f#

我正在尝试用F#写一个Monad但是我无法编译代码而且我收到错误FS0001错误:这个表达式预计会有类型'Result'但是这里有类型'(Result <'a> - > Result << b>) - >结果<'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 
Run Code Online (Sandbox Code Playgroud)

Tom*_*cek 5

首先,你的类型bind是不对的:

your version : Result<'a> -> (Result<'a> -> Result<'b>) -> Result<'b>
typical type : Result<'a> -> ('a -> Result<'b>) -> Result<'b>
Run Code Online (Sandbox Code Playgroud)

如果你改变参数的顺序,那么完成剩下的工作也会容易得多:

bind : ('a -> Result<'b>) -> Result<'a> -> Result<'b>
Run Code Online (Sandbox Code Playgroud)

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

let bind f x = 
    match x with 
    | Success x -> f x
    | Failure -> Failure
Run Code Online (Sandbox Code Playgroud)

完成此操作后,您可以定义bindIsPositivebindToString.该bind操作现在将函数作为第一个参数,因此这可以工作,但您必须删除类型注释:

let bindIsPositive =  bind isPositive 
let bindToString = bind toString
Run Code Online (Sandbox Code Playgroud)

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

let strintToIntIsPositiveIntToString x =  x |> stringToInt |> bindIsPositive |> bindToString
let strintToIntIsPositiveIntToString x =  x >>= stringToInt >>= isPositive >>= toString
Run Code Online (Sandbox Code Playgroud)