Skip to content

Instantly share code, notes, and snippets.

@Savelenko
Created September 25, 2023 10:04
Show Gist options
  • Save Savelenko/8ff918ffdaa06760fd3fd79e7461e467 to your computer and use it in GitHub Desktop.
Save Savelenko/8ff918ffdaa06760fd3fd79e7461e467 to your computer and use it in GitHub Desktop.
When a HOF breaks in F#
// A polymorphic function which works for values of *any* type.
let hello (a : 't) : string =
// Just ignore the argument
"Hello"
// We can use it any context, on any input: it is polymorphic after all.
let result =
let a = hello 1
let b = hello "string"
a + b
// We are doing FP here, so replacing a constant with a variable is a standard
// technique, for example for constant `1` above. By doing so `result` becomes
// a function:
let result2 i =
let a = hello i // Constant `1` became variable `i` in this expression
let b = hello "string"
a + b
// So far so good. But functions are also values, so instead of replacing `1` with
// a variable, let's replace constant `hello` with a variable. By doing so `result`
// becomes a higher-order function:
let result3 f =
let a = f 1 // Constant `hello` became variable `f` in this and other expressions
let b = f "string" // Type error here: "This expression was expected to be int"
a + b
// Whoops! We applied seemingly the same transformation (replace a constant with a
// variable), but it does not work! It means F# is not uniform in handling values
// as functions, at least not in all cases. Most people are surprised by this example,
// followed by a slight disappointment and rightfully so.
//
// This is because F# type system does not support higher-ranked types (HRT, not to
// be confused with HKT). However, it is well-known that this can be "fixed" by using
// object methods. HRT are supported in some other FP languages natively for functions,
// without methods and objects.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment