Scott encoded lists can be defined as followed:
newtype List a =
List {
uncons :: forall r. r -> (a -> List a -> r) -> r
}
As opposed to the ADT version List
is both type and data constructor. Scott encoding determines ADTs through pattern matching, which essentially means removing one layer of constructors. Here is the full uncons
operation without implicit arguments:
uncons :: r -> (a -> List a -> r) -> List a -> r
-- Nil ^ ^^^^^^^^^^^^^^^^^^ Cons
uncons nil cons (List f) = f nil cons
This makes perfect sense. uncons
takes a constant, a continuation and a List
and produces whatever value.
The type of the data constructor, however, doesn't make much sense to me:
List :: (forall r. r -> (a -> List a -> r) -> r) -> List a
I see that r
has its own scope but this isn't very helpful. Why are r
and List a
flipped compared to uncons
? And why are there additional parentheses on the LHS?
I'm probably muddling up type and term level here..
uncons
. If you look at its actual type, you seeList
anduncons
are just inverses (List :: something -> something else; uncons :: something else -> something
). – HTNWuncons
operation without implicit arguments" - where did you get that from? The "implicit argument"List a
comes first, and produces the type of the "field". – Bergiuncons'
. It is not meant to be the written out version of the newtype declaration. I put theList
argument at the end for convenience.List
's type still doesn't make sense to me. It is a type level lambda which takes another type level lambda as an argument and produces a list. I cannot make the connection to the term level. – Iven Marquardtcons True nil
the second parameter needs to be a list (butnil
is not a list!). Lists are functions of two parameters\nil _ -> nil
would be a list. Putting it together results in:List (\_ cons -> cons True (List (\nil _ -> nil)))
– Micha Wiedenmann