Consider unlifted functions
Motivation
Unlifted types give programmers the ultimate guarantee that their data is really data and does not contain references to arbitrarily large thunks. So, taking this advice by heart one may write an unlifted list data type:
type List :: UnliftedType -> UnliftedType
data List a = Nil | Cons a (List a)
Now one might want to write an applicative-like operator:
ap :: List (a -> b) -> List a -> List b
However, this is not a valid type, because the function a -> b
is not an unlifted type as List
expects.
Cases like this are common. While spending a few moments trying to implement an unlifted prelude I also came across this:
type ST :: Type -> UnliftedType -> UnliftedType
newtype ST s a = ST (State# s -> (# State# s, a #))
Again, this is not legal, because for this to be allowed as a newtype, we would need the inner type to be an unlifted function.
Proposed Changes
I would like to have an unlifted function type so I can write:
ap :: List (a -!> b) -> List a -> List b
And I could define these unlifted functions like this:
id1 :: a -!> a
id1 x = x
id2 :: a -!> a
id2 = \x -> x
So both function definitions and lambdas should be able to introduce these unlifted functions. Perhaps not yet at the top level while we're still figuring out #17521, but eventually that would be nice to have too.