(* val tp_reduce : tp * knd * spine -> tp tp_reduce (a, k, sp) computes the result of reducing (.\ .\ ... .\ a) . sp assuming (.\ .\ ... .\ a) : k (where the number of lambdas is the number of pis found in k) *) and tp_reduce (a, k, sp) = let fun subst_tpfn s (tpfnLam a) = tpfnLam(subst_tpfn (OneDotShift s) a) | subst_tpfn s (tpfnType a) = tpfnType(subst_tp s a) fun tp_reduce'(tpfnLam(a), KPi(_,b,k), h::sp) = let val s = TermDot(termof h, b, Id) val a' = subst_tpfn s a val k' = subst_knd s k in tp_reduce' (a', k', sp) end | tp_reduce' (tpfnType a, Type, ) = a | tp_reduce' _ = raise Syntax "simplified-kind mismatch in type reduction" fun wrap (a, KPi(_,b,k)) = tpfnLam (wrap(a,k)) | wrap (a, Type) = tpfnType a val aw = wrap (a, k) in tp_reduce' (aw, k, sp) endto fill a gaping functionality/correctness hole in my typechecker (god damn defined type families with more than one argument!) and it magically typechecked and compiled and passed all tests the first time. That hardly ever happens to me anymore. Very satisfying.
A paper on describing circuits in an agda DSL: http://www.staff.science.uu.nl/~swier004/publications/2015-types-draft.pdf
Going more carefully now through this little tutorial on fpga programming with the iCEstick. It's in spanish, which makes it slightly more…
Some further progress cleaning up the https://xkcd.com/1360/ -esque augean stables that is my hard drive. Tomato chicken I made a couple days ago…