robkuz
robkuz

Reputation: 9934

inlining a map function (Functor)

I am trying to write a polymorphic map(Functor) but I get stopped a this type error.

Given the following type

type Result<'TSuccess, 'TError> = 
    | Success of 'TSuccess 
    | Error of 'TError list
    with 
    member this.map f =
        match this with
            | Success(s) -> Success(f s)
            | Error(e) -> Error e

and this inline function

let inline (<!>) (f: ^A -> ^B) (t:^T) = 
    let map' = (^T : (member map : (^A -> ^B) -> ^T) (t, f))
    map'

and this calling code

(fun x y -> x + y) <!> (Success 3);;

I get this error

(fun x y -> x + y) <!> (Success 3);;
--------------------------------^
/Users/robkuz/stdin(404,33): error FS0001: 
This expression was expected to have type
 'a -> 'b
but here has type
 int

I dont understand why this is so? There is nothing where I specify that ^T must be of type
^T<('a->'b>)> which is not possible anyways in F#.

btw. the call like (fun x -> x + 1) <!> (Success 3) will work fine

Upvotes: 3

Views: 92

Answers (1)

Perhaps I missing something obvious but doesn't it work with just a small change to <!>?

type Result<'TSuccess, 'TError> = 
  | Success of 'TSuccess 
  | Error   of 'TError list
  with 
  member this.map (f : 'TSuccess -> 'T) =
    match this with
    | Success s -> Success (f s)
    | Error   e -> Error e

let inline (<!>) (f : ^A -> ^B) (t : ^T) : ^U =
  let map' = (^T : (member map : (^A -> ^B) -> ^U) (t, f))
  map'

[<EntryPoint>]
let main argv = 
  let w = (fun x y -> x + y) <!> Success 3
  let x = (fun x -> x 2) <!> w
  printfn "%A" x // Prints "Success 5"
  0

Upvotes: 3

Related Questions