F#Monad如何修复数据类型

时间:2019-02-09 00:40:03

标签: f# monads

我正在尝试用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 

1 个答案:

答案 0 :(得分:5)

首先,您的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