<div><span style="font-family:arial,helvetica,sans-serif">Here is a considerably longer worked example using the analogy to J, borrowing heavily from Wadler:</span></div><div><font face="courier new, monospace"><br></font></div>
<div><div class="gmail_quote">As J, this doesn&#39;t really add any power, but perhaps when used with non-representable functors like Equivalence/Comparison you can do something more interesting.</div></div><div class="gmail_quote">
<br></div><div><font face="courier new, monospace">-- Used for Hilbert</font></div><div><font face="courier new, monospace">{-# LANGUAGE DefaultSignatures, TypeOperators #-}</font></div><div><font face="courier new, monospace"><br>
</font></div><div><font face="courier new, monospace">-- Used for Representable</font></div><div><font face="courier new, monospace">{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, </font><span style="font-family:&#39;courier new&#39;,monospace">FlexibleContexts, FlexibleInstances #-}</span></div>
<div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">module Search where</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">import Control.Applicative</font></div>
<div><font face="courier new, monospace">import Data.Function (on)</font></div><div><font face="courier new, monospace">import Data.Functor.Contravariant</font></div><div><font face="courier new, monospace">import GHC.Generics -- for Hilbert</font></div>
<div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">newtype Search f a = Search { optimum :: f a -&gt; a }</font></div><div><font face="courier new, monospace"><br></font></div>
<div><font face="courier new, monospace">instance Contravariant f =&gt; Functor (Search f) where</font></div><div><font face="courier new, monospace">  fmap f (Search g) = Search $ f . g . contramap f</font></div><div><font face="courier new, monospace"><br>
</font></div><div><font face="courier new, monospace">instance Contravariant f =&gt; Applicative (Search f) where</font></div><div><font face="courier new, monospace"> pure a = Search $ \_ -&gt; a</font></div><div><font face="courier new, monospace"> Search fs &lt;*&gt; Search as = Search $ \k -&gt; </font></div>
<div><font face="courier new, monospace">   let </font><span style="font-family:&#39;courier new&#39;,monospace">go f = f (as (contramap f k)) </span></div><div><font face="courier new, monospace">   in  </font><span style="font-family:&#39;courier new&#39;,monospace">go (fs (contramap go k))</span></div>
<div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">instance Contravariant f =&gt; Monad (Search f) where</font></div><div><font face="courier new, monospace">  return a = Search $ \_ -&gt; a</font></div>
<div><font face="courier new, monospace">  Search ma &gt;&gt;= f = Search $ \k -&gt; </font></div><div><font face="courier new, monospace">    optimum (f (ma (contramap (\a -&gt; optimum (f a) k) k))) k</font></div><div><font face="courier new, monospace"><br>
</font></div><div><font face="courier new, monospace">class Contravariant f =&gt; Union f where</font></div><div><font face="courier new, monospace">  union :: Search f a -&gt; Search f a -&gt; Search f a</font></div><div>
<font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">instance Union Predicate where</font></div><div><font face="courier new, monospace">  union (Search ma) (Search mb) = Search $ \ p -&gt; case ma p of</font></div>
<div><font face="courier new, monospace">    a | getPredicate p a -&gt; a</font></div><div><font face="courier new, monospace">      | otherwise        -&gt; mb p</font></div><div><font face="courier new, monospace"><br></font></div>
<div><font face="courier new, monospace">instance Ord r =&gt; Union (Op r) where</font></div><div><font face="courier new, monospace">  union (Search ma) (Search mb) = Search $ \ f -&gt; let</font></div><div><font face="courier new, monospace">      a = ma f</font></div>
<div><font face="courier new, monospace">      b = mb f</font></div><div><font face="courier new, monospace">    in if getOp f a &gt;= getOp f b then a else b</font></div><div><font face="courier new, monospace"><br></font></div>
<div><font face="courier new, monospace">both :: Union f =&gt; a -&gt; a -&gt; Search f a</font></div><div><font face="courier new, monospace">both = on union pure</font></div><div><font face="courier new, monospace"><br>
</font></div><div><font face="courier new, monospace">fromList :: Union f =&gt; [a] -&gt; Search f a</font></div><div><font face="courier new, monospace">fromList = foldr1 union . map return</font></div><div><font face="courier new, monospace"><br>
</font></div><div><div><font face="courier new, monospace">class Contravariant f =&gt; Neg f where</font></div><div><font face="courier new, monospace">  neg :: f a -&gt; f a</font></div><div><font face="courier new, monospace"><br>
</font></div><div><font face="courier new, monospace">instance Neg Predicate where</font></div><div><font face="courier new, monospace">  neg (Predicate p) = Predicate (not . p)</font></div><div><font face="courier new, monospace"><br>
</font></div><div><font face="courier new, monospace">instance Num r =&gt; Neg (Op r) where</font></div><div><font face="courier new, monospace">  neg (Op f) = Op (negate . f)</font></div><div><font face="courier new, monospace"><br>
</font></div><div><font face="courier new, monospace">pessimum :: Neg f =&gt; Search f a -&gt; f a -&gt; a</font></div><div><font face="courier new, monospace">pessimum m p = optimum m (neg p)</font></div></div><div><font face="courier new, monospace"><br>
</font></div><div><div><div><font face="courier new, monospace">forsome :: Search Predicate a -&gt; (a -&gt; Bool) -&gt; Bool</font></div><div><font face="courier new, monospace">forsome m p = p (optimum m (Predicate p))</font></div>
<div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">forevery :: Search Predicate a -&gt; (a -&gt; Bool) -&gt; Bool</font></div><div><font face="courier new, monospace">forevery m p = p (pessimum m (Predicate p))</font></div>
<div><font face="courier new, monospace"><br></font></div></div></div><div><div><font face="courier new, monospace">member :: Eq a =&gt; a -&gt; Search Predicate a -&gt; Bool</font></div><div><font face="courier new, monospace">member a x = forsome x (== a)</font></div>
<div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">each :: (Union f, Bounded a, Enum a) =&gt; Search f a</font></div><div><font face="courier new, monospace">each = fromList [minBound..maxBound]</font></div>
<div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">bit :: Union f =&gt; Search f Bool</font></div><div><font face="courier new, monospace">bit = fromList [False,True]</font></div>
<div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">cantor :: Union f =&gt; Search f [Bool]</font></div><div><font face="courier new, monospace">cantor = sequence (repeat bit)</font></div>
<div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">least :: (Int -&gt; Bool) -&gt; Int</font></div><div><font face="courier new, monospace">least p = head [ i | i &lt;- [0..], p i ]</font></div>
<div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">infixl 4 --&gt;</font></div><div><font face="courier new, monospace">(--&gt;) :: Bool -&gt; Bool -&gt; Bool</font></div><div>
<font face="courier new, monospace">p --&gt; q = not p || q</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">fan :: Eq r =&gt; ([Bool] -&gt; r) -&gt; Int</font></div>
<div><font face="courier new, monospace">fan f = least $ \ n -&gt;</font></div><div><font face="courier new, monospace">          forevery cantor $ \x -&gt;</font></div><div><font face="courier new, monospace">            forevery cantor $ \y -&gt;</font></div>
<div><font face="courier new, monospace">              (take n x == take n y) --&gt; (f x == f y)</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">-- a length check that can handle infinite lists</font></div>
<div><font face="courier new, monospace">compareLength :: [a] -&gt; Int -&gt; Ordering</font></div><div><font face="courier new, monospace">compareLength xs n = case drop (n - 1) xs of</font></div><div><font face="courier new, monospace">   []  -&gt; LT</font></div>
<div><font face="courier new, monospace">   [_] -&gt; EQ</font></div><div><font face="courier new, monospace">   _   -&gt; GT</font></div><div class="gmail_quote"></div></div><div><font face="courier new, monospace"><br></font></div>
<div><font face="courier new, monospace">-- Now, lets leave Haskell 98 behind</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">-- Using the new GHC generics to derive versions of Hilbert&#39;s epsilon</font></div>
<div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">class GHilbert t where</font></div><div><font face="courier new, monospace">  gepsilon :: Union f =&gt; Search f (t a)</font></div>
<div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">class Hilbert a where</font></div><div><font face="courier new, monospace">  -- <a href="http://en.wikipedia.org/wiki/Epsilon_calculus">http://en.wikipedia.org/wiki/Epsilon_calculus</a></font></div>
<div><font face="courier new, monospace">  epsilon :: Union f =&gt; Search f a</font></div><div><font face="courier new, monospace">  default epsilon :: (Union f, GHilbert (Rep a), Generic a) =&gt; Search f a</font></div>
<div><font face="courier new, monospace">  epsilon = fmap to gepsilon</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">instance GHilbert U1 where</font></div><div>
<font face="courier new, monospace">  gepsilon = return U1</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">instance (GHilbert f, GHilbert g) =&gt; GHilbert (f :*: g) where</font></div>
<div><font face="courier new, monospace">  gepsilon = liftA2 (:*:) gepsilon gepsilon</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">instance (GHilbert f, GHilbert g) =&gt; GHilbert (f :+: g) where</font></div>
<div><font face="courier new, monospace">  gepsilon = fmap L1 gepsilon `union` fmap R1 gepsilon</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">instance GHilbert a =&gt; GHilbert (M1 i c a) where</font></div>
<div><font face="courier new, monospace">  gepsilon = fmap M1 gepsilon</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">instance Hilbert a =&gt; GHilbert (K1 i a) where</font></div>
<div><font face="courier new, monospace">  gepsilon = fmap K1 epsilon</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">instance Hilbert ()</font></div><div><font face="courier new, monospace">instance (Hilbert a, Hilbert b) =&gt; Hilbert (a, b)</font></div>
<div><font face="courier new, monospace">instance (Hilbert a, Hilbert b, Hilbert c) =&gt; Hilbert (a, b, c)</font></div><div><font face="courier new, monospace">instance (Hilbert a, Hilbert b, Hilbert c, Hilbert d) =&gt; </font></div>
<div><font face="courier new, monospace">  Hilbert (a, b, c, d)</font></div><div><font face="courier new, monospace">instance (Hilbert a, Hilbert b, Hilbert c, Hilbert d, Hilbert e) =&gt;</font></div><div><font face="courier new, monospace">  Hilbert (a, b, c, d, e)</font></div>
<div><font face="courier new, monospace">instance Hilbert Bool</font></div><div><font face="courier new, monospace">instance Hilbert Ordering</font></div><div><span style="font-family:&#39;courier new&#39;,monospace">instance Hilbert a =&gt; Hilbert [a]</span></div>
<div><font face="courier new, monospace">instance Hilbert a =&gt; Hilbert (Maybe a)</font></div><div><font face="courier new, monospace">instance (Hilbert a, Hilbert b) =&gt; Hilbert (Either a b)</font></div><div><font face="courier new, monospace">instance Hilbert Char where </font></div>
<div><font face="courier new, monospace">  epsilon = each</font></div><div><font face="courier new, monospace">instance (Union f, Hilbert a) =&gt; Hilbert (Search f a) where</font></div><div><font face="courier new, monospace">  epsilon = fmap fromList epsilon</font></div>
<div><div><font face="courier new, monospace"><br></font></div></div><div><div><span style="font-family:&#39;courier new&#39;,monospace">search :: (Union f, Hilbert a) =&gt; f a -&gt; a</span></div><div><font face="courier new, monospace">search = optimum epsilon</font></div>
</div><div><font face="courier new, monospace"><br></font></div><div><div><font face="courier new, monospace">find :: Hilbert a =&gt; (a -&gt; Bool) -&gt; a</font></div><div><font face="courier new, monospace">find = optimum epsilon . Predicate</font></div>
<div><font face="courier new, monospace"><br></font></div><div><span style="font-family:&#39;courier new&#39;,monospace">every :: Hilbert a =&gt; (a -&gt; Bool) -&gt; Bool</span></div><div><font face="courier new, monospace">every = forevery epsilon</font></div>
<div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">exists :: Hilbert a =&gt; (a -&gt; Bool) -&gt; Bool</font></div><div><font face="courier new, monospace">exists = forsome epsilon</font></div>
</div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">-- and MPTCs/Fundeps to define representable contravariant functors:</font></div><div><font face="courier new, monospace"><br>
</font></div><div><font face="courier new, monospace">class Contravariant f =&gt; Representable f r | f -&gt; r where</font></div><div><font face="courier new, monospace">  represent :: f a -&gt; a -&gt; r</font></div><div>
<font face="courier new, monospace">  tally     :: (a -&gt; r) -&gt; f a</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">instance Representable (Op r) r where</font></div>
<div><font face="courier new, monospace">  represent (Op f) = f</font></div><div><font face="courier new, monospace">  tally = Op</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">instance Representable Predicate Bool where</font></div>
<div><font face="courier new, monospace">  represent (Predicate p) = p</font></div><div><font face="courier new, monospace">  tally = Predicate</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">supremum :: Representable f r =&gt; Search f a -&gt; (a -&gt; r) -&gt; r</font></div>
<div><font face="courier new, monospace">supremum m p = p (optimum m (tally p))</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">infimum :: (Representable f r, Neg f) =&gt; Search f a -&gt; (a -&gt; r) -&gt; r</font></div>
<div><font face="courier new, monospace">infimum m p = p (pessimum m (tally p))</font></div><div><font face="courier new, monospace"><br></font></div><div class="gmail_quote"><div class="gmail_quote">A few toy examples:  </div>
<div class="gmail_quote"><font face="courier new, monospace"><br></font></div><div class="gmail_quote"><font face="courier new, monospace">ghci&gt; supremum (fromList [1..10] :: Search (Op Int) Int) id</font></div><div class="gmail_quote">
<font face="courier new, monospace">10</font></div><div class="gmail_quote"><font face="courier new, monospace">ghci&gt; find (==&#39;a&#39;)</font></div><div class="gmail_quote"><font face="courier new, monospace">&#39;a&#39;</font></div>
<div class="gmail_quote"><font face="courier new, monospace">ghci&gt; fan (!!4)</font></div><div class="gmail_quote"><font face="courier new, monospace">5</font></div></div><div class="gmail_quote"><font face="courier new, monospace">ghci&gt; find (\xs -&gt; compareLength xs 10 == EQ &amp;&amp; (xs !! 4) == &#39;a&#39;) </font></div>
<div class="gmail_quote"><div class="gmail_quote"><font face="courier new, monospace">&quot;\NUL\NUL\NUL\NULa\NUL\NUL\NUL\NUL\NUL&quot;</font></div></div><div class="gmail_quote"><br></div><div class="gmail_quote">-Edward</div>