I rarely have this struggle nowadays with F#, but then again type inheritance is much less common with F#, so perhaps I was just lucky. Or I am missing the obvious. Normally when the compiler complains about not knowing a certain type I reverse the order of pipes or composition operands and I'm done.
Basically, given a function call that works as g(f x)
, it also works as x |> f |> g
or (f >> g) x
. But today it doesn't...
Here's a messy proof-of-concept of what I mean:
module Exc =
open System
type MyExc(t) = inherit Exception(t)
let createExc t = new MyExc(t)
type Ex = Ex of exn
type Res = Success of string | Fail of Ex with
static member createRes1 t = Ex(createExc(t)) |> Fail // compiled
static member createRes2 t = t |> createExc |> Ex |> Fail // FS0001
static member createRes3 = createExc >> Ex >> Fail // FS0001
Normally, this works (at least in my experience). The lines with "fail" throw:
error FS0001: Type mismatch. Expecting a MyExc -> 'a but given a exn -> Ex. The type 'MyExc' does not match the type 'exn'
Not a big deal, not hard to workaround, but I happen to have to write a lot of code where composition is the easier/cleaner approach and I don't wish to write a bunch of utility functions that I have to put in everywhere.
I looked at flexible types, as I guess this is a contravariance problem, but I don't see how I can apply it here. Any ideas to keep this idiomatic?
Note, if I rearrange, i.e. as Ex << createExc >> Fail
or using the pipe-backward operator I end up with the same error on a different part.