F # Monad как исправить типы данных - PullRequest
0 голосов
/ 09 февраля 2019

Я пытаюсь написать монаду на F #, но не могу скомпилировать код, и я получаю сообщение об ошибке FS0001 error: ожидалось, что это выражение будет иметь тип 'Result', но здесь имеет тип '(Result <' a> ->Результат <'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 

1 Ответ

0 голосов
/ 09 февраля 2019

Прежде всего, тип вашего 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...