Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
short example of a place where rank2types and rankntypes are necessary
{-# LANGUAGE Rank2Types #-}
-- This is a small example of where you need to use Rank2Types (or
-- RankNTypes).
-- The 'a' type is being used polymorphically here, but when it
-- is called, it will already be bound (as either an Int or String),
-- so it cannot be used polymorphically.
-- This means that g is a monomorphic function.
-- The forall at the outermost level means that f promises to work with
-- any argument g as long as g has the shape a -> a for some type a unknown
-- to f.
--f :: forall a. Show a => (a -> a) -> IO ()
--f g = do
-- print $ g 1
-- print $ g "lala"
-- The 'a' type here is being used polymorphically, however f' get's to
-- pick what to use for a, not the caller. This is why you need
-- higher-rank types. Without higher-rank types, the caller always get to
-- pick the types.
-- This means that g' must be a polymorphic function.
-- The forall at the inner level means that it's the argument g' who
-- promises to be of shape a -> a for all types a at the same time,
-- and it's f' who makes use of that promise by choosing both a = Int
-- and a = String.
f' :: (forall a. Show a => a -> a) -> IO ()
f' g' = do
print $ g' 1
print $ g' "lala"
main :: IO ()
main = f' id
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment