3 ms·
For what purpose? Surely the type checker doesn't recognize the equivalence. a1 :: a r1 :: r f :: a -> r f a1 = r1 b :: (a -> r) -> r
by gohrt 13y ago
For what purpose? Surely the type checker doesn't recognize the equivalence.
a1 :: a
r1 :: r
f :: a -> r
f a1 = r1
b :: (a -> r) -> r
b f = f a1 -- == r1
but `a f` is ill-typed.
m :: a -> (a -> r) -> r
m a1 f = f a1 -- m === (flip ($)) === (flip id)
So it appears that `(a -> r) -> r` is a "co-value" that can be applied to a function (resulting in the application of the function to the underlying vale of type `a`, dual to the usual situation where functions are applied to values.
- tel 13y agoThis is pretty much exactly correct. The common terminology is that `forall r . (a -> r) -> r` is the Continuation Passing Style transformed version of `a`. At the end of the day, `CPS a` is useful whenever CPS is, but also more often. sometimes you see CPS (a.k.a. Church-encoded) forms of values in Haskell in really tight inner loops as the compiler can optimize them better. You also see a variant of it occurring in Free monad structures because it allows you to re-associate the binds to make them much more efficient. You also see it sometimes when making monads over categories other than Hask—it lets you pretend you're working with a Hask monad (and thus use do notation) for a while and only "pass through" the real category at fixed points in time. This lets you, for instance, write a monad for Set even though normally you couldn't due to the need for the Ord constraint.