Online, (Scala/Java) and Haskell-specific tutorials on existential types seem to be dominant. Because I wouldn’t get stuck too much on notation, I went with Haskell tutorials, and they all seem to imply that existentials that are unconstrained are useless.
The usual example for existentials is information (but not trait) hiding, in which for example you can have a definition like so (with some syntax parallels for those unfamiliar with haskell):
{-
ocaml: `type gadt = Constr : typexpr`
haskell: `data Gadt where Constr :: typexpr`
-}
data Hidden where
Hide :: Show a => a -> Hidden
{-
ocaml: iter (fun (Hide x) -> ...) [Hide 1; Hide ...]
-}
main :: IO ()
main =
mapM_ (\(Hide x) -> print x) [Hide 1, Hide "a", Hide 4.2]
The problem with such implication is that I can’t find a usage for an existential introduced by an OCaml GADT because I don’t know how I’d express the Show a => a
constraint.
type hidden = Hide : 'a -> hidden
Would simply completely cloak 'a
, and any attempt at interacting with it would produce a type scope escaping error.
That considered, since Show a => a
is best emulated now with passing a first-class module, that was the vector I was walking in with my existentials experiments, but I have a feeling there’s better, more valid, usage of those type variables that isn’t reliant on constraining.
So my question is, have you ever come across a pattern where an existential type variable is the solution?