
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>niche computing science &#187; Types</title>
	<atom:link href="http://www.iis.sinica.edu.tw/~scm/tag/types/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.iis.sinica.edu.tw/~scm</link>
	<description>Research Blog of 穆信成 Shin-Cheng Mu</description>
	<lastBuildDate>Mon, 21 Nov 2011 11:53:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Developing Programs and Proofs Spontaneously using GADT</title>
		<link>http://www.iis.sinica.edu.tw/~scm/2007/developing-programs-and-proofs-spontaneously-using-gadt/</link>
		<comments>http://www.iis.sinica.edu.tw/~scm/2007/developing-programs-and-proofs-spontaneously-using-gadt/#comments</comments>
		<pubDate>Mon, 06 Aug 2007 05:55:49 +0000</pubDate>
		<dc:creator>Shin</dc:creator>
				<category><![CDATA[Research Blog]]></category>
		<category><![CDATA[Curry-Howard]]></category>
		<category><![CDATA[Dependent Type]]></category>
		<category><![CDATA[GADT]]></category>
		<category><![CDATA[Haskell]]></category>
		<category><![CDATA[Types]]></category>

		<guid isPermaLink="false">http://www.iis.sinica.edu.tw/~scm/?p=32</guid>
		<description><![CDATA[I am curious about the possibility of developing Haskell programs spontaneously with proofs about their properties and have the type checker verify the proofs for us, in a way one would do in a dependently typed language. I tried to redo part of the merge-sort example in <a href="http://www.e-pig.org/downloads/ydtm.pdf">Altenkirch, McBride, and McKinna's introduction to Epigram</a>: deal the input list into a binary tree, and fold the tree by the function merging two sorted lists into one.]]></description>
			<content:encoded><![CDATA[<p><i>This entry was also posted to the <a href="http://article.gmane.org/gmane.comp.lang.haskell.cafe/27062">Haskell-Cafe</a> mailing list.</i></p>
<p>I am curious about the possibility of developing Haskell programs spontaneously with proofs about their properties and have the type checker verify the proofs for us, in a way one would do in a dependently typed language.</p>
<p>In the exercise below, I tried to redo part of the merge-sort example in <a href="http://www.e-pig.org/downloads/ydtm.pdf">Altenkirch, McBride, and McKinna&#8217;s introduction to Epigram</a>: deal the input list into a binary tree, and fold the tree by the function merging two sorted lists into one. The property I am going to show is merely that the length of the input list is preserved.</p>
<p>Given that dependent types and GADTs are such popular topics, I believe the same must have been done before, and there may be better ways to do it. If so, please give me some comments or references. Any comments are welcomed.</p>
<pre><code>> {-# OPTIONS_GHC -fglasgow-exts #-}</code>
</pre>
<p>To begin with, we define the usual type-level representation of natural numbers and lists indexed by their lengths.</p>
<pre><code>> data Z = Z       deriving Show
> data S a = S a   deriving Show

> data List a n where
>   Nil :: List a Z
>   Cons :: a -> List a n -> List a (S n)</code></pre>
<h3>Append</h3>
<p>To warm up, let us see the familiar &#8220;append&#8221; example. Unfortunately, unlike <a href="http://web.cecs.pdx.edu/~sheard/Omega/">Omega</a>, Haskell does not provide type functions. I am not sure which is the best way to emulate type functions. One possibility is to introduce the following GADT:</p>
<pre><code>> data Plus m n k where    --- m + n = k
>   PlusZ :: Plus Z n n
>   PlusS :: Plus m n k -> Plus (S m) n (S k)</code></pre>
<p>such that <code>Plus m n k</code> represents a proof that <code>m + n = k</code>.</p>
<p>Not having type functions, one of the possible ways to do append is to have the function, given two lists of lengths <code>m</code> and <code>n</code>, return a list of length <code>k</code> and a proof that <code>m + n = k</code>. Thus, the type of append would be:</p>
<pre><code>   append :: List a m -> List a n
               -> exists k. (List a k, Plus m n k)
</code></pre>
<p>In Haskell, the existential quantifier is mimicked by <code>forall</code>. We define:</p>
<pre><code>> data DepSum a p = forall i . DepSum (a i) (p i)
</code></pre>
<p>The term &#8220;dependent sum&#8221; is borrowed from the <a href="http://web.cecs.pdx.edu/~sheard/papers/GADT+ExtKinds.ps<br />
">Omega tutorial of Sheard, Hook, and Linger</a>. <a href="http://article.gmane.org/gmane.comp.lang.haskell.cafe/27086">Derek Elkins</a> and <a href="http://article.gmane.org/gmane.comp.lang.haskell.cafe/27088">Dan Licata</a> explained to me why they are called dependent sums, rather than products.</p>
<p>The function <code>append</code> can thus be defined as:
<pre><code>> append :: List a m -> List a n -> DepSum (List a) (Plus m n)
> append Nil ys = DepSum ys PlusZ
> append (Cons x xs) ys =
>    case (append xs ys) of
>      DepSum zs p -> DepSum (Cons x zs) (PlusS p)</code></pre>
<p>Another possibility is to provide <code>append</code> a proof that <code>m + n = k</code>. The type and definition of <code>append</code> would be:</p>
<pre><code>< append :: Plus m n k -> List a m -> List a n -> List a k
< append PlusZ Nil ys = ys
< append (PlusS pf) (Cons x xs) ys = Cons x (append pf xs ys)</code></pre>
<p>I thought the second <code>append</code> would be more difficult to use: to append two lists, I have to provide a proof about their lengths! It turns out that this append actually composes easier with other parts of the program. We will come to this later.</p>
<h3>Some Lemmas</h3>
<p>Here are some lemmas represented as functions on terms. The function <code>incAssocL</code>, for example, converts a proof of <code>m + (1+n) = k</code> to a proof of <code>(1+m) + n = k</code>.</p>
<pre><code>> incAssocL :: Plus m (S n) k -> Plus (S m) n k
> incAssocL PlusZ = PlusS PlusZ
> incAssocL (PlusS p) = PlusS (incAssocL p)

> incAssocR :: Plus (S m) n k -> Plus m (S n) k
> incAssocR (PlusS p) = plusMono p

> plusMono :: Plus m n k -> Plus m (S n) (S k)
> plusMono PlusZ = PlusZ
> plusMono (PlusS p) = PlusS (plusMono p)</code></pre>
<p>For example, the following function revcat performs list reversal by an accumulating parameter. The invariant we maintain is <code>m + n = k</code>. To prove that the invariant holds, we have to use <code>incAssocL</code>.</p>
<pre><code>> revcat :: List a m -> List a n -> DepSum (List a) (Plus m n)
> revcat Nil ys = DepSum ys PlusZ
> revcat (Cons x xs) ys =
>     case revcat xs (Cons x ys) of
>        DepSum zs p -> DepSum zs (incAssocL p)</code></pre>
<h3>Merge</h3>
<p>Apart from the proof manipulations, the function <code>merge</code> is not very different from what one would expect:</p>
<pre><code>> merge :: Ord a => List a m -> List a n -> DepSum (List a) (Plus m n)
> merge Nil ys = DepSum ys PlusZ
> merge (Cons x xs) Nil = append (Cons x xs) Nil
> merge (Cons x xs) (Cons y ys)
>   | x <= y = case merge xs (Cons y ys) of
>                  DepSum zs p -> DepSum (Cons x zs) (PlusS p)
>   | otherwise = case merge (Cons x xs) ys of
>                   DepSum zs p -> DepSum (Cons y zs) (plusMono p)</code></pre>
<p>The lemma <code>plusMono</code> is used to convert a proof of <code>m + n = k</code> to a proof of <code>m + (1+n) = 1+k</code>.</p>
<h3>Sized Trees</h3>
<p>We also index binary trees by their sizes:</p>
<pre><code>> data Tree a n where
>   Nul :: Tree a Z
>   Tip :: a -> Tree a (S Z)
>   Bin :: Tree a n1 -> Tree a n ->
>             (Plus p n n1, Plus n1 n k) -> Tree a k</code></pre>
<p>The two trees given to the constructor <code>Bin</code> have sizes <code>n1</code> and <code>n</code> respectively. The resulting tree, of size <code>k</code>, comes with a proof that <code>n1 + n = k</code>. Furthermore, we want to maintain an invariant that <code>n1</code> either equals <code>n</code>, or is bigger than <code>n</code> by one. This is represented by the proof <code>Plus p n n1</code>. In the definition of <code>insertT</code> later, <code>p</code> is either <code>PlusZ</code> or <code>PlusS PlusZ</code>.</p>
<h3>Lists to Trees</h3>
<p>The function <code>insertT</code> inserts an element into a tree:</p>
<pre><code>> insertT :: a -> Tree a n -> Tree a (S n)
> insertT x Nul = Tip x
> insertT x (Tip y) = Bin (Tip x) (Tip y) (PlusZ, PlusS PlusZ)
> insertT x (Bin t u (PlusZ, p)) =
>      Bin (insertT x t) u (PlusS PlusZ, PlusS p)
> insertT x (Bin t u (PlusS PlusZ, p)) =
>      Bin t (insertT x u) (PlusZ, PlusS (incAssocR p))</code></pre>
<p>Note that whenever we construct a tree using <code>Bin</code>, the first proof, corresponding to the difference in size of the two subtrees, is either <code>PlusZ</code> or <code>PlusS PlusZ</code>.</p>
<p>The counterpart of <code>foldr</code> on indexed list is defined by:</p>
<pre><code>> foldrd :: (forall k . (a -> b k -> b (S k))) -> b Z
>               -> List a n -> b n
> foldrd f e Nil = e
> foldrd f e (Cons x xs) = f x (foldrd f e xs)</code></pre>
<p>The result is also an indexed type (<code>b n</code>).</p>
<p>The function <code>deal :: List a n -> Tree a n</code>, building a tree out of a list, can be defined as a fold:</p>
<pre><code>> deal :: List a n -> Tree a n
> deal = foldrd insertT Nul</code></pre>
<h3>Trees to Lists, and Merge Sort</h3>
<p>The next step is to fold through the tree by the function <code>merge</code>. The first two clauses are simple:</p>
<pre><code>> mergeT :: Ord a => Tree a n -> List a n
> mergeT Nul = Nil
> mergeT (Tip x) = Cons x Nil</code></pre>
<p>For the third clause, one would wish that we could write something as simple as:
<pre><code>   mergeT (Bin t u (_,p1)) =
      case merge (mergeT t) (mergeT u) of
        DepSum xs p -> xs</code></pre>
<p>However, this does not type check. Assume that <code>t</code> has size <code>n1</code>, and <code>u</code> has size <code>n</code>. The <code>DepSum</code> returned by <code>merge</code> consists of a list of size <code>i</code>, and a proof <code>p</code> of type <code>Plus m n i</code>, for some <code>i</code>. The proof <code>p1</code>, on the other hand, is of type <code>P m n k</code> for some <code>k</code>. Haskell does not know that <code>Plus m n</code> is actually a function and cannot conclude that <code>i=k</code>.</p>
<p>To explicitly state the equality, we assume that there is a function <code>plusFn</code> which, given a proof of <code>m + n = i</code> and a proof of <code>m + n = k</code>, yields a function converting an <code>i</code> in any context to a <code>k</code>. That is:</p>
<pre><code>   plusFn :: Plus m n i -> Plus m n k
               -> (forall f . f i -> f k)</code></pre>
<p>The last clause of <code>mergeT</code> can be written as:</p>
<pre><code>mergeT (Bin t u (_,p1)) =
   case merge (mergeT t) (mergeT u) of
     DepSum xs p -> plusFn p p1 xs</code></pre>
<p>How do I define <code>plusFn</code>? On Haskell-Cafe, Jim Apple <a href="http://article.gmane.org/gmane.comp.lang.haskell.cafe/27070">suggested this implementation</a> (by the way, he maintains a <a href="http://blog.jbapple.com/">very interesting blog on typed programming</a>):</p>
<pre><code>  plusFn :: Plus m n h -> Plus m n k -> f h -> f k
  plusFn PlusZ PlusZ x = x
  plusFn (PlusS p1) (PlusS p2) x =
      case plusFn p1 p2 Equal of
        Equal -> x

  data Equal a b where
      Equal :: Equal a a</code></pre>
<p>Another implementation, which looks closer to the previous work on type equality [<a href="#3">3</a>, <a href="#4">4</a>, <a href="#5">5</a>], was suggested by <a href="http://article.gmane.org/gmane.comp.lang.haskell.cafe/27074">apfelmus</a>:</p>
<pre><code>> newtype Equal a b = Proof { coerce :: forall f . f a -> f b }

> newtype Succ f a  = InSucc { outSucc :: f (S a) }

> equalZ :: Equal Z Z
> equalZ = Proof id

> equalS :: Equal m n -> Equal (S m) (S n)
> equalS (Proof eq) = Proof (outSucc . eq . InSucc)

> plusFnEq :: Plus m n i -> Plus m n k -> Equal i k
> plusFnEq PlusZ     PlusZ     = Proof id
> plusFnEq (PlusS x) (PlusS y) = equalS (plusFn x y)

> plusFn :: Plus m n i -> Plus m n k -> f i -> f k
> plusFn p1 p2 = coerce (plusFnEq p1 p2)</code></pre>
<p>Now that we have both <code>deal</code> and <code>mergeT</code>, merge sort is simply their composition:</p>
<p><code>> msort :: Ord a => List a n -> List a n<br />
> msort = mergeT . deal</code></p>
<p>The function <code>mergeT</code> can be defined using a fold on trees as well. Such a fold might probably look like this:</p>
<pre><code>> foldTd :: (forall m n k . Plus m n k -> b m -> b n -> b k)
>           -> (a -> b (S Z)) -> b Z
>           -> Tree a n -> b n
> foldTd f g e Nul = e
> foldTd f g e (Tip x) = g x
> foldTd f g e (Bin t u (_,p)) =
>    f p (foldTd f g e t) (foldTd f g e u)

   mergeT :: Ord a => Tree a n -> List a n
   mergeT = foldTd merge' (\x -> Cons x Nil) Nil
    where merge' p1 xs ys =
            case merge xs ys of
              DepSum xs p -> plusFn p p1 xs</code></pre>
<p>I am not sure whether this is a "reasonable" type for <code>foldTd</code>.</p>
<h3>Passing in the Proof as an Argument</h3>
<p>Previously I thought the second definition of append would be more difficult to use, because we will have to construct a proof about the lengths before calling append. In the context above, however, it may actually be more appropriate to use this style of definitions.</p>
<p>An alternative definition of merge taking a proof as an argument can be defined by:</p>
<pre><code>< merge :: Ord a => Plus m n k -> List a m ->
<                       List a n -> List a k
< merge PlusZ Nil ys = ys
< merge pf (Cons x xs) Nil = append pf (Cons x xs) Nil
< merge (PlusS p) (Cons x xs) (Cons y ys)
<   | x <= y    = Cons x (merge p xs (Cons y ys))
<   | otherwise = Cons y (merge (incAssocL p) (Cons x xs) ys)</code></pre>
<p>A definition of <code>mergeT</code> using this definition of <code>merge</code> follows immediately because we can simply use the proof coming with the tree:</p>
<pre><code>< mergeT :: Ord a => Tree a n -> List a n
< mergeT Nul = Nil
< mergeT (Tip x) = Cons x Nil
< mergeT (Bin t u (_,p1)) =
<   merge p1 (mergeT t) (mergeT u)</code></pre>
<p>I don't know which approach can be called more "natural". However, both <a href="http://article.gmane.org/gmane.comp.lang.haskell.cafe/27070">Jim Apple</a> and <a href="http://article.gmane.org/gmane.comp.lang.haskell.cafe/27074">apfelmus</a> pointed out that <em>type families</em>, a planned new feature of Haskell, may serve as a kind of type functions. With type families, the append example would look like ( code from <a href="http://article.gmane.org/gmane.comp.lang.haskell.cafe/27074">apfelmus</a>): </p>
<pre><code>  type family   Plus :: * -> * -> *
  type instance Plus Z n     = n
  type instance Plus (S m) n = S (Plus m n)

  append :: (Plus m n ~ k) => List a m -> List a n -> List a k
  append Nil         ys = ys
  append (Cons x xs) ys = Cons x (append xs ys)</code></pre>
<p>apfelmus commented that "viewed with the dictionary translation for type classes in mind, this is probably exactly the alternative type of append you propose: <code>append :: Plus m n k -> List a m -> List a n -> List a k</code>".</p>
<h3>References</h3>
<ul>
<li>[1] Thorsten Altenkirch, Conor McBride, and James McKinna. <a href="http://www.e-pig.org/downloads/ydtm.pdf<br />
">Why Dependent Types Matter</a>.</li>
<li>[2] Tim Sheard, James Hook, and Nathan Linger. <a href="http://web.cecs.pdx.edu/~sheard/papers/GADT+ExtKinds.ps">GADTs + Extensible Kinds = Dependent Programming</a>.</li>
<li><a name="3">[3]</a> James Cheney, Ralf Hinze. A lightweight implementation of generics and dynamics.</li>
<li><a name="4">[4]</a> Stephanie Weirich, Type-safe cast: (functional pearl), ICFP 2000.</li>
<li><a name="5">[5]</a>Arthur I. Baars , S. Doaitse Swierstra, Typing dynamictyping, ACM SIGPLAN Notices, v.37 n.9, p.157-166, September 2002</li>
</ul>
<h3>Appendix. Auxiliary Functions</h3>
<pre><code>> instance Show a => Show (List a n) where
>  showsPrec _ Nil = ("[]"++)
>  showsPrec _ (Cons x xs) = shows x . (':':) . shows xs

> instance Show (Plus m n k) where
>   showsPrec _ PlusZ = ("pZ"++)
>   showsPrec p (PlusS pf) = showParen (p>=10) (("pS " ++) .
>                              showsPrec 10 pf)

> instance Show a => Show (Tree a n) where
>   showsPrec _ Nul = ("Nul"++)
>   showsPrec p (Tip x) = showParen (p >= 10) (("Tip " ++) . shows x)
>   showsPrec p (Bin t u pf) =
>     showParen (p>=10)
>      (("Bin "++) . showsPrec 10 t . (' ':) . showsPrec 10 u .
>       (' ':) . showsPrec 10 pf)</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.iis.sinica.edu.tw/~scm/2007/developing-programs-and-proofs-spontaneously-using-gadt/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Encoding Inductive and Coinductive Types in Polymorphic Lambda Calculus</title>
		<link>http://www.iis.sinica.edu.tw/~scm/2007/encoding-inductive-and-coinductive-types-in-polymorphic-lambda-calculus/</link>
		<comments>http://www.iis.sinica.edu.tw/~scm/2007/encoding-inductive-and-coinductive-types-in-polymorphic-lambda-calculus/#comments</comments>
		<pubDate>Fri, 27 Jul 2007 04:29:17 +0000</pubDate>
		<dc:creator>Shin</dc:creator>
				<category><![CDATA[Research Blog]]></category>
		<category><![CDATA[Haskell]]></category>
		<category><![CDATA[Types]]></category>
		<category><![CDATA[λ calculus]]></category>

		<guid isPermaLink="false">http://www.iis.sinica.edu.tw/~scm/?p=31</guid>
		<description><![CDATA[An indcutive type &#956;F is simulated by <code> forall x . (F x -> x) -> x</code>, while a coinductive type &#957;F is simulatd by <code> exists x . (x -> F x, x)</code>. When they coincide, we can build hylomorphisms, but also introduces non-termination into the language.]]></description>
			<content:encoded><![CDATA[<p>This was written about two years ago. Mostly inspired by <a href="http://homepages.inf.ed.ac.uk/wadler/">Philip Wadler</a>&#8216;s note <a href="http://homepages.inf.ed.ac.uk/wadler/papers/free-rectypes/free-rectypes.txt">Recursive types for free</a>.</p>
<h3>Inductive types</h3>
<p>Inductive types are least fixed-points. An indcutive type &mu;F is simulated by </p>
<pre><code> forall x . (F x -> x) -> x</code></pre>
<p>In Haskell, we <a href="http://www.iis.sinica.edu.tw/~scm/?p=28">need a constructor to wrap a &#8220;forall&#8221; quantifier</a>.</p>
<pre><code>> newtype LFix f = LF (forall x. (f x -> x) -> x)
> instance Show (LFix f) where
>   show _ = "<LFix>"

> foldL :: Functor f => (f x -> x) -> LFix f -> x
> foldL f (LF x) = x f

> inL :: Functor f => f (LFix f) -> LFix f
> inL fx = LF (\\f -> f . fmap (foldL f) $ fx)

> outL :: Functor f => LFix f -> f (LFix f)
> outL = foldL (fmap inL)
</code></pre>
<p>Example: lists.</p>
<pre><code>> data F a x = L | R a x deriving Show
> instance Functor (F a) where
>   fmap f L = L
>   fmap f (R a x) = R a (f x)

> type ListL a = LFix (F a)
</code></pre>
<p>A  <code>ListL</code> can only be constructed out of nil and cons.
<pre><code>    Main> consL 1 (consL 2 (consL 3 nilL))
   <LFix>
</code></pre>
<pre><code>> nilL = inL L
> consL a x = inL (R a x)
</code></pre>
<p>We can convert a ListL to a &#8216;real&#8217; Haskell list.
<pre><code>
   Main> lList $ consL 1 (consL 2 (consL 3 nilL))
   [1,2,3]
</code></pre>
<pre><code>> lList :: LFix (F a) -> [a]
> lList = foldL ll
>   where ll L = []
>         ll (R a x) = a : x
</code></pre>
<p>However, a <code>ListL</code> has to be explicitly built, so there is no infinite <code>ListL</code>.</p>
<h3>Coinductive types</h3>
<p>A coinductive type &nu;F is simulatd by
<pre><code> exists x . (x -> F x, x)
</code></pre>
<p>We represent it in Haskell using the property <code>exists x . F x  == forall y . (forall x . F x -> y) -> y</code>:</p>
<pre><code>> data GFix f = forall x . GF (x -> f x, x)
> instance Show (GFix f) where
>   show _ = "<GFix>"

> unfoldG :: Functor f => (x -> f x) -> x -> GFix f
> unfoldG g x = GF (g,x)

> outG :: Functor f => GFix f -> f (GFix f)
> outG (GF (g,x)) = fmap (unfoldG g) . g $ x

> inG :: Functor f => f (GFix f) -> GFix f
> inG = unfoldG (fmap outG)
</code></pre>
<p>Example:</p>
<pre><code>> type ListG a = GFix (F a)
</code></pre>
<p><code>ListG</code> can be constructed out of <code>nil</code> and <code>cons</code>, as well as an unfold.</p>
<pre><code>> nilG = inG L
> consG a x = inG (R a x)

> fromG :: Int -> ListG Int
> fromG m = unfoldG ft m
>    where ft m = R m (m+1)
</code></pre>
<p>However, one can perform only a finite number of outG.</p>
<pre><code>  Main> fmap outG . outG . fromG $ 1
  R 1 (R 2 <GFix>)
</code></pre>
<h3>Isomorphism</h3>
<p>The function <code>force</code> witnesses the isomorphism between <code>LFix</code> and <code>GFix</code>.</p>
<pre><code>> force :: Functor f => GFix f -> LFix f
> force = inL . fmap force . outG     -- recursion!
</code></pre>
<p>If  <code>LFix</code> and <code>GFix</code> are isomorphic, we are allowed to build hylomorphisms:</p>
<pre><code>> fromTo :: Int -> Int -> LFix (F Int)
> fromTo m n = takeLessThan n . force . fromG $ m

> takeLessThan :: Int -> LFix (F Int) -> LFix (F Int)
> takeLessThan n = foldL (tlt n)
>   where tlt n L = nilL
>         tlt n (R m x) | n <= m = nilL
>                       | otherwise = consL m x

  Main> lList (fromTo 1 10)
  [1,2,3,4,5,6,7,8,9]
</code></pre>
<p>However, <code>force</code> has to be defined using general recursion. The price is that it is now possible to write programs that do not terminate.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.iis.sinica.edu.tw/~scm/2007/encoding-inductive-and-coinductive-types-in-polymorphic-lambda-calculus/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Polymorphic Types in Haskell without Constructors?</title>
		<link>http://www.iis.sinica.edu.tw/~scm/2007/polymorphic-types-without-constructors/</link>
		<comments>http://www.iis.sinica.edu.tw/~scm/2007/polymorphic-types-without-constructors/#comments</comments>
		<pubDate>Sat, 30 Jun 2007 06:22:58 +0000</pubDate>
		<dc:creator>Shin</dc:creator>
				<category><![CDATA[Research Blog]]></category>
		<category><![CDATA[Haskell]]></category>
		<category><![CDATA[Types]]></category>

		<guid isPermaLink="false">http://www.iis.sinica.edu.tw/~scm/?p=28</guid>
		<description><![CDATA[I was trying to simulate church numerals and primitive recursion in second rank polymorphism of Haskell. However, polymorphic types in Haskell can only be instantiated with monomorphic types.]]></description>
			<content:encoded><![CDATA[<p>I wrote this during Feb. 2005. Since it occurs to me every once in a while and I kept forgetting the details, I&#8217;d better keep a note.</p>
<p>I was trying to simulate church numerals and primitive recursion in second rank polymorphism of Haskell, and I thought I could do it without introducing a constructor by <code>newtype</code>. Church&#8217;s encoding of natural numbers can be expressed by the type:
<pre><code>> type N = forall a . (a -> a) -> a -> a</code></pre>
<h3>Basics</h3>
<p>We first define <code>zero</code>, <code>succ</code>, and some constants:
<pre><code>> zero :: N
> zero = \f -> \a ->  a

> succ :: N -> N
> succ n = \f -> \a -> f (n f a)

> toInt :: N -> Int
> toInt n = n (1+) 0

> one, two, three :: N
> one = succ zero
> two = succ one
> three = succ two
</code></pre>
<p>Addition and multiplication can be defined as usual:
<pre><code>> add, mul :: N -> N -> N
> add m n = \f -> \a -> m f (n f a)
> mul m n = \f -> \a -> m (n f) a</code></pre>
<h3>Predecessor</h3>
<p>Even <code>pred</code> typechecks &#8212; at least this particular version of <code>pred</code>:</p>
<pre><code>> pred :: N -> N
> pred n f x = n (\g h -> h (g f)) (const x) id</code></pre>
<p>I am more familiar with another way to implement <code>pred</code>, which uses pairs. This <code>pred</code>, on the other hand, can be understood by observing that the &#8220;fold&#8221; part returns a function that abstracts away the outermost <code>f</code>:
<pre><code>  pred n f x = dec n id
    where dec 0 = \h -> x
          dec (1+n) = \h -> h (f^n x)
</code></pre>
<h3>Exponential</h3>
<p>I know of two ways to define <code>exp</code>. However, only this one typechecks:
<pre><code>> exp :: N -> N -> N
> exp m n = n m</code></pre>
<p>Another definition, making use of <code>mul</code>, does <em>not</em> typecheck!</p>
<pre><code>  exp :: N -> N -> N
  exp m n = n (mul m) one</code></pre>
<p>GHC returns a rather cryptic error message &#8220;Inferred type is less polymorphic than expected. Quantified type variable `a&#8217; escapes.&#8221; The real reason is that polymorphic types in Haskell can only be instantiated with monomorphic types. If we spell out the explicit type applications, we get:</p>
<pre><code>   exp  (m::N) (n::N) = n [N] ((mul m)::N->N) (one::N)</code></pre>
<p>which is not allowed. On the other hand, the previous definition of <code>exp</code> does not instantiate type variables to polymorphic types:</p>
<pre><code>   exp (m::N) (n::N) = /\b -> \(f::(b->b)) -> \(x::b) -> n[b->b] (m[b]) f x
</code></pre>
<p>For the same reason, primitive recursion does not type check:
<pre><code> primrec :: (N -> a -> a) -> a -> N -> a
 primrec f c n =
   snd (n (\z -> pair (succ (fst z))
                      (f (fst z) (snd z)))
          (pair zero c))</code></pre>
<p>nor does the pair-based definition of <code>pred</code>. </p>
<p>To overcome the problem we have to wrap <code>N</code> in <code>newtype</code>. The solution was <a href="http://okmij.org/ftp/Haskell/types.html#some-impredicativity">presented by Oleg Kiselyov</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.iis.sinica.edu.tw/~scm/2007/polymorphic-types-without-constructors/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Substraction not Definable in Simply Typed Lambda Calculus</title>
		<link>http://www.iis.sinica.edu.tw/~scm/2007/substraction-not-definable-in-simply-typed-lambda-calculus/</link>
		<comments>http://www.iis.sinica.edu.tw/~scm/2007/substraction-not-definable-in-simply-typed-lambda-calculus/#comments</comments>
		<pubDate>Thu, 21 Jun 2007 07:55:36 +0000</pubDate>
		<dc:creator>Shin</dc:creator>
				<category><![CDATA[Research Blog]]></category>
		<category><![CDATA[Types]]></category>
		<category><![CDATA[λ calculus]]></category>

		<guid isPermaLink="false">http://www.iis.sinica.edu.tw/~scm/?p=27</guid>
		<description><![CDATA[We can even define primitive recursion, only that it does not have the desired type <code>primrec :: (N -> b -> b) -> b -> N -> b</code>. Therefore, predecessor does not get the type <code>pred :: N a -> N a</code> either.]]></description>
			<content:encoded><![CDATA[<p>I probably wrote this a couple of years ago when I was studying polymorphic types.</p>
<p>What happens if we have only monomorphic type when we define church numerals? Let us represent church numerals by the type <code>(a -> a) -> a -> a</code> for some monomorphic <code>a</code>:
<pre><code>> import Prelude hiding (succ, pred)

> type N a = (a -> a) -> a -> a</code></pre>
<p>Zero and successor can still be defined. Their values do not matter.
<pre><code>> zero :: N a
> zero = error ""

> succ :: N a -> N a
> succ = error ""</code></pre>
<p>Also assume we have pairs predefined:
<pre><code>> pair a b = (a,b)</code></pre>
<p>We can even define primitive recursion, only that it does not have the desired type:
<pre><code>  primrec :: (N -> b -> b) -> b -> N -> b</code></pre>
<p>Instead we get the type below:
<pre><code>> primrec :: (N a -> b -> b) -> b -> N (N a, b) -> b
> primrec f c n =
>   snd (n (\z -> pair (succ (fst z))
>                      (f (fst z) (snd z)))
>          (pair zero c))</code></pre>
<p>Therefore, predecessor does not get the type <code>pred :: N a -> N a<br />
</code> we want. Instead we have:
<pre><code>> pred :: N (N a, N a) -> N a
> pred = primrec (\n m -> n) zero</code></pre>
<h3>Ref.</h3>
<p>Oleg Kiselyov, <a href="http://okmij.org/ftp/Computation/lambda-calc.html#predecessor">Predecessor and lists are not representable in simply typed lambda-calculus</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.iis.sinica.edu.tw/~scm/2007/substraction-not-definable-in-simply-typed-lambda-calculus/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

