我正在尝试用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
答案 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
执行此操作后,可以定义bindIsPositive
和bindToString
。 bind
操作现在将函数作为第一个参数,因此可以使用,但是您必须删除类型注释:
let bindIsPositive = bind isPositive
let bindToString = bind toString
编写函数时,可以使用>>=
运算符,也可以使用常规的F#管道和bind
函数:
let strintToIntIsPositiveIntToString x = x |> stringToInt |> bindIsPositive |> bindToString
let strintToIntIsPositiveIntToString x = x >>= stringToInt >>= isPositive >>= toString