Reputation: 57
I am trying to write a Monad in F# but I can not compile the code and I am getting error FS0001 error: This expression was expected to have type 'Result' but here has type '(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
Upvotes: 3
Views: 86
Reputation: 243041
First of all, the type of your bind
is not right:
your version : Result<'a> -> (Result<'a> -> Result<'b>) -> Result<'b>
typical type : Result<'a> -> ('a -> Result<'b>) -> Result<'b>
It will also be a lot easier to do the rest if you switch the order of parameters to get:
bind : ('a -> Result<'b>) -> Result<'a> -> Result<'b>
So, you can use the following bind
:
let bind f x =
match x with
| Success x -> f x
| Failure -> Failure
Once you do this, you can define bindIsPositive
and bindToString
. The bind
operation now takes a function as a first argument, so this works but you have to remove your type annotation:
let bindIsPositive = bind isPositive
let bindToString = bind toString
When composing functions, you can then either use your >>=
operator, or use normal F# piping and bind
functions:
let strintToIntIsPositiveIntToString x = x |> stringToInt |> bindIsPositive |> bindToString
let strintToIntIsPositiveIntToString x = x >>= stringToInt >>= isPositive >>= toString
Upvotes: 5