Search code examples
genericstypesfunctional-programmingf#language-design

Do any languages implement retained generics on functions passed as parameters?


Ran across this in F# today:

let test<'a> (f: 'a -> unit) =
    let x = f 123
    let y = f "wow"
    ()

Which produces a compiler error, since the generic parameter must be the same within each call of test<'a> as described here: Type inference not working when passing map function

While this makes sense, it made me curious if there are any other languages out there that have implemented something like this--maybe a sort of "parameter-level generics"?

As a follow up, what are the challenges to implementing something like this?


Solution

  • Sure. In Haskell, such things are called "higher rank types": they are types in which you are allowed to "move quantification inside parentheses":

    test :: (forall a. a -> ()) -> ()
    test f = let x = f 123
                 y = f "wow"
             in ()
    

    The "challenge" is also described in the link given:

    Rank-N type reconstruction is undecidable in general, and some explicit type annotations are required in their presence.

    Just rank-2 types are decidable, though, AFAIK (see here). That's why there are two different flags for enabling them in GHC.