How to fix "incompatible parts" error

let noneIfEmptyString = (value: string, cvt: string => 'a):option<'a> => {
    if value == "" {
      None
    } else {
      value->cvt->Some
    }
  }
let intValue = noneIfEmptyString("0",int_of_string)
let floatValue = noneIfEmptyString("0",float_of_string)

I try this code , but got error:

This has type: string => float
Somewhere wanted: string => int

The incompatible parts:
  float vs int

This can be fixed using a locally abstract type:

let noneIfEmptyString = (type a, value: string, cvt: string => a): option<
  a,
> => {
  if value == "" {
    None
  } else {
    value->cvt->Some
  }
}

More on locally abstract types here:

Although the original code compiles fine as well: Playground

thank you, it work !

Just something to be aware of: type parameters in the implementation signature are actually unification variables, meaning they will unify with (become) the first type that the compiler infers from the function body. If you want real type parameters locally abstract types are one way to do it but I’d say the more idiomatic way would be to not annotate the implementation, instead to write an interface file with the type signature of the function:

let noneIfEmptyString: (string, string => 'a) => option<'a>
3 Likes