gdritter repos documents / master scraps / tup.md
master

Tree @master (Download .tar.gz)

tup.md @masterview markup · raw · history · blame

-- In this case, a^n corresponds to an n-tuple whose elements are of type a -- We have a typeclass

class Conv a b where conv :: a -> b

-- And types corresponding to

type Tup t = forall n : Nat. t ^ n type Var t = forall n : Nat. (forall s. Conv s t => s) ^ n

-- we also have these two built-in primitives

generalize :: Var t -> Tup t forget :: Tup t -> [t]

-- that will usually be used together

var :: Var t -> [t]

-- We could use this to create 'variadic' functions, e.g. -- a non-type-safe but C-like printf

data PFElem = PFInt Int | PFFloat Float | PFString String

instance Conv Int PFElem where conv = PFInt instance Conv Float PFElem where conv = PFFloat instance Conv String PFElem where conv = PFString

printf :: String -> Var PFElem -> IO () printf spec args = putStr . printfInterpolate . var $ args where printfInterpolate :: String -> [PFElem] -> String printfInterpolate = {- ... -}

main :: IO () main = printf "string %s and int %d\n" ("foo", 5)


-- In Latka, we will have the Var type and the var primitive as built-ins, -- and treats a^n as a subtype of Var a in all cases. Thus, we can convert a -- value like <2,3> : Nat * Nat to a value of type Var Nat, but not the other -- way around.

-- With that machinery, we can define the following as a library:

-- word instance Conv String WordPart where {- ... -} instance Conv Word WordPart where {- ... -}

wd : Var WordPart -> Word wd = {- ... -}

-- this is well-typed, because its argument is of type String * Word <: Var WordPart puts wd.<"foo", wd.<"bar", "baz">> -- this is not, because its argument is of type String * String * (Nat * Nat) -- puts wd.<"a","b",<1,2>>

-- sentence instance Conv String SentencePart where {- ... -} instance Conv Word SentencePart where {- ... -} instance Conv Sentence SentencePart where {- ... -}

se : Var SentencePart -> Sentence se = {- ... -}

-- this is well-typed, as the argument is of type -- String * Word * Sentence <: Var SentencePart puts se.<"one", wd.<"two", "three">, se.<"four", "five">>

-- &c

--this gives us type-safe variadic functions, as well as a nice mechanism for --semi-implicitly stringifying things

cat : Var String -> String cat vs = go.(var.vs) where go [] = "" go (x::xs) = x (go.xs)

{- prints "foo5<>" -} puts cat.<"foo", 5, <>>