countable (empty) → 0.1
raw patch · 6 files changed
+887/−0 lines, 6 filesdep +basesetup-changed
Dependencies added: base
Files
- LICENSE +10/−0
- Setup.lhs +6/−0
- countable.cabal +43/−0
- src/Data/Countable.hs +423/−0
- src/Data/Empty.hs +63/−0
- src/Data/Searchable.hs +342/−0
+ LICENSE view
@@ -0,0 +1,10 @@+countable is Copyright (c) Ashley Yakeley, 2010.+All rights reserved.++Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:++- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.++- Neither name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.lhs view
@@ -0,0 +1,6 @@+#!/usr/bin/runhaskell +> module Main where+> import Distribution.Simple+> main :: IO ()+> main = defaultMain+
+ countable.cabal view
@@ -0,0 +1,43 @@+cabal-version: >= 1.6++name: countable+version: 0.1++license: BSD3+license-file: LICENSE+copyright: Ashley Yakeley <ashley@semantic.org>+maintainer: Ashley Yakeley <ashley@semantic.org>+author: Ashley Yakeley <ashley@semantic.org>+category: Data+synopsis: Countable, Searchable, Finite, Empty classes+description:+ * @class Countable@, for countable types+ .+ * @class AtLeastOneCountable@, for countable types that have at least one value+ .+ * @class InfiniteCountable@, for infinite countable types+ .+ * @class Searchable@, for types that can be searched over. This turns out to include some infinite types, see <http://math.andrej.com/2007/09/28/seemingly-impossible-functional-programs/>.+ .+ * @class Finite@, for finite types+ .+ * @class Empty@, for empty types+ .+ * @data Nothing@, an empty type+ .+ Some orphan instances:+ .+ * @(Searchable a,Eq b) => Eq (a -> b)@ / /+ .+ * @(Finite t) => Foldable ((->) t)@ / /+ .+ * @(Finite a) => Traversable ((->) a)@ / /+ .+ * @(Show a,Finite a,Show b) => Show (a -> b)@ / /++build-type: Simple+build-depends: base == 4.*+extensions: EmptyDataDecls ExistentialQuantification+hs-source-dirs: src+ghc-options: -Wall+exposed-modules: Data.Searchable Data.Countable Data.Empty
+ src/Data/Countable.hs view
@@ -0,0 +1,423 @@+module Data.Countable where+{+ import Data.Word;+ import Data.Int;+ import Prelude;++ class (Eq a) => Countable a where+ {+ countPrevious :: a -> Maybe a;+ countMaybeNext :: Maybe a -> Maybe a;+ };++ countDown :: (Countable a) => a -> [a];+ countDown a = case countPrevious a of+ {+ Just a' -> a':(countDown a');+ Nothing -> [];+ };++ instance Countable () where+ {+ countPrevious () = Nothing;+ countMaybeNext Nothing = Just ();+ countMaybeNext (Just ()) = Nothing;+ };++ instance Countable Bool where+ {+ countPrevious True = Just False;+ countPrevious False = Nothing;+ countMaybeNext Nothing = Just False;+ countMaybeNext (Just False) = Just True;+ countMaybeNext (Just True) = Nothing;+ };++ boundedCountPrevious :: (Eq a,Bounded a,Enum a) => a -> Maybe a;+ boundedCountPrevious n | n == minBound = Nothing;+ boundedCountPrevious n = Just (pred n);++ boundedCountMaybeNext :: (Eq a,Bounded a,Enum a) => Maybe a -> Maybe a;+ boundedCountMaybeNext Nothing = Just minBound;+ boundedCountMaybeNext (Just n) | n == maxBound = Nothing;+ boundedCountMaybeNext (Just n) = Just (succ n);++ instance Countable Word8 where+ {+ countPrevious = boundedCountPrevious;+ countMaybeNext = boundedCountMaybeNext;+ };++ instance Countable Word16 where+ {+ countPrevious = boundedCountPrevious;+ countMaybeNext = boundedCountMaybeNext;+ };++ instance Countable Word32 where+ {+ countPrevious = boundedCountPrevious;+ countMaybeNext = boundedCountMaybeNext;+ };++ instance Countable Word64 where+ {+ countPrevious = boundedCountPrevious;+ countMaybeNext = boundedCountMaybeNext;+ };++ instance Countable Int8 where+ {+ countPrevious = boundedCountPrevious;+ countMaybeNext = boundedCountMaybeNext;+ };++ instance Countable Int16 where+ {+ countPrevious = boundedCountPrevious;+ countMaybeNext = boundedCountMaybeNext;+ };++ instance Countable Int32 where+ {+ countPrevious = boundedCountPrevious;+ countMaybeNext = boundedCountMaybeNext;+ };++ instance Countable Int64 where+ {+ countPrevious = boundedCountPrevious;+ countMaybeNext = boundedCountMaybeNext;+ };++ instance Countable Integer where+ {+ countPrevious 0 = Nothing;+ countPrevious a | a < 0 = Just (- a - 1);+ countPrevious a = Just (- a);+ countMaybeNext = Just . countNext;+ };++ instance (Countable a) => Countable (Maybe a) where+ {+ countPrevious = fmap countPrevious;+ countMaybeNext Nothing = Just Nothing;+ countMaybeNext (Just ma) = fmap Just (countMaybeNext ma);+ };++ maybeRecount :: (Countable a,Countable b) => a -> Maybe b;+ maybeRecount a = case countPrevious a of+ {+ Just a' -> do+ {+ b' <- maybeRecount a';+ countMaybeNext b';+ };+ Nothing -> countMaybeNext Nothing;+ };++ {-+ Right 0+ Left 0+ Right 1+ Left 1+ Left 2+ Left 3+ -}++ instance (Countable a,Countable b) => Countable (Either a b) where+ {+ countPrevious (Right b) = case countPrevious b of+ {+ Just b' -> case maybeRecount b' of+ {+ Just a -> Just (Left a);+ Nothing -> Just (Right b);+ };+ Nothing -> Nothing;+ };+ countPrevious (Left a) = case maybeRecount a of+ {+ Just b -> Just (Right b);+ Nothing -> fmap Left (countPrevious a);+ };++ countMaybeNext Nothing = case countMaybeNext Nothing of+ {+ Just b -> Just (Right b);+ Nothing -> fmap Left (countMaybeNext Nothing);+ };+ countMaybeNext (Just (Right b)) = case maybeRecount b of+ {+ Just a -> Just (Left a);+ Nothing -> fmap Right (countMaybeNext (Just b));+ };+ countMaybeNext (Just (Left a)) = case maybeRecount a >>= (countMaybeNext . Just) of+ {+ Just b -> (Just (Right b));+ Nothing -> fmap Left (countMaybeNext (Just a));+ };+ };++ countDownUp :: (Countable down,Countable up) => (down,up) -> Maybe (down,up);+ countDownUp (down,up) = do+ {+ down' <- countPrevious down;+ up' <- countMaybeNext (Just up);+ return (down',up');+ };++ countUpDown :: (Countable up,Countable down) => (up,down) -> Maybe (up,down);+ countUpDown (up,down) = do+ {+ up' <- countMaybeNext (Just up);+ down' <- countPrevious down;+ return (up',down');+ };++ finalIteration :: (a -> Maybe a) -> a -> a;+ finalIteration f a = case f a of+ {+ Just a' -> finalIteration f a';+ Nothing -> a;+ };++ instance (Countable a,Countable b) => Countable (a,b) where+ {+ countPrevious ab = case countUpDown ab of+ {+ Just ab' -> Just ab';+ _ -> let+ {+ (a',b') = finalIteration countDownUp ab;+ } in case countPrevious a' of+ {+ Just a'' -> Just (a'',b');+ Nothing -> case countPrevious b' of+ {+ Just b'' -> Just (a',b'');+ Nothing -> Nothing;+ };+ };+ };++ countMaybeNext Nothing = do+ {+ a <- countMaybeNext Nothing;+ b <- countMaybeNext Nothing;+ return (a,b);+ };+ countMaybeNext (Just ab) = case countDownUp ab of+ {+ Just ab' -> Just ab';+ _ -> let+ {+ (a',b') = finalIteration countUpDown ab;+ } in case countMaybeNext (Just a') of+ {+ Just a'' -> Just (a'',b');+ Nothing -> case countMaybeNext (Just b') of+ {+ Just b'' -> Just (a',b'');+ Nothing -> Nothing;+ };+ };+ };+ };++ class (Countable a) => AtLeastOneCountable a where+ {+ countFirst :: a;+ };++ instance AtLeastOneCountable () where+ {+ countFirst = ();+ };++ instance AtLeastOneCountable Bool where+ {+ countFirst = False;+ };++ instance AtLeastOneCountable Word8 where+ {+ countFirst = minBound;+ };++ instance AtLeastOneCountable Word16 where+ {+ countFirst = minBound;+ };++ instance AtLeastOneCountable Word32 where+ {+ countFirst = minBound;+ };++ instance AtLeastOneCountable Word64 where+ {+ countFirst = minBound;+ };++ instance AtLeastOneCountable Int8 where+ {+ countFirst = minBound;+ };++ instance AtLeastOneCountable Int16 where+ {+ countFirst = minBound;+ };++ instance AtLeastOneCountable Int32 where+ {+ countFirst = minBound;+ };++ instance AtLeastOneCountable Int64 where+ {+ countFirst = minBound;+ };++ instance AtLeastOneCountable Integer where+ {+ countFirst = 0;+ };++ instance (Countable a) => AtLeastOneCountable (Maybe a) where+ {+ countFirst = Nothing;+ };++ instance (Countable a,AtLeastOneCountable b) => AtLeastOneCountable (Either a b) where+ {+ countFirst = Right countFirst;+ };++ instance (AtLeastOneCountable a,AtLeastOneCountable b) => AtLeastOneCountable (a,b) where+ {+ countFirst = (countFirst,countFirst);+ };++ class (AtLeastOneCountable a) => InfiniteCountable a where+ {+ countNext :: Maybe a -> a;+ };++ instance InfiniteCountable Integer where+ {+ countNext Nothing = 0;+ countNext (Just a) | a < 0 = - a;+ countNext (Just a) = - a - 1;+ };++ instance (InfiniteCountable a) => InfiniteCountable (Maybe a) where+ {+ countNext = fmap countNext;+ };++ instance (AtLeastOneCountable a,InfiniteCountable b) => InfiniteCountable (a,b) where+ {+ countNext Nothing = (countFirst,countNext Nothing);+ countNext (Just ab) = case countDownUp ab of+ {+ Just ab' -> ab';+ _ -> let+ {+ (a',b') = finalIteration countUpDown ab;+ } in case countMaybeNext (Just a') of+ {+ Just a'' -> (a'',b');+ Nothing -> (a',countNext (Just b'));+ };+ };+ };++ recount :: (Countable a,InfiniteCountable b) => a -> b;+ recount = countNext . (fmap recount) . countPrevious;++ instance (Countable a,InfiniteCountable b) => InfiniteCountable (Either a b) where+ {+ countNext Nothing = Right (countNext Nothing);+ countNext (Just (Right b)) = case maybeRecount b of+ {+ Just a -> Left a;+ Nothing -> Right (countNext (Just b));+ };+ countNext (Just (Left a)) = Right (countNext (recount a));+ };++ instance (Countable a) => Countable [a] where+ {+ countPrevious [] = Nothing;+ countPrevious (x:xs) = case countMaybeNext Nothing of+ {+ Nothing -> seq x undefined; -- x not supposed to exist+ Just firsta -> Just (pp x xs) where+ {+ pp a r = case countPrevious a of+ {+ Just a' -> firsta:(pp a' r);+ Nothing -> case r of+ {+ [] -> [];+ b:r' -> case countMaybeNext (Just b) of+ {+ Just b' -> b':r';+ Nothing -> firsta:(pp b r');+ };+ };+ };+ };+ };++ countMaybeNext Nothing = Just [];+ countMaybeNext (Just l) = case countMaybeNext Nothing of+ {+ Nothing -> Nothing;+ Just firsta -> Just (countNext' l) where+ {+ countNext' [] = [firsta];+ countNext' (a:r) = case countPrevious a of+ {+ Just a' -> firsta:a':r;+ Nothing -> upOne (countNext' r);+ };++ upOne [] = [firsta];+ upOne (a:r) = case countMaybeNext (Just a) of+ {+ Just a' -> a':r;+ Nothing -> firsta:a:r;+ };+ };+ };+ };++ instance (Countable a) => AtLeastOneCountable [a] where+ {+ countFirst = [];+ };++ instance (AtLeastOneCountable a) => InfiniteCountable [a] where+ {+ countNext Nothing = [];+ countNext (Just l) = countNext' l where+ {+ countNext' [] = [countFirst];+ countNext' (a:r) = case countPrevious a of+ {+ Just a' -> countFirst:a':r;+ Nothing -> upOne (countNext' r);+ };++ upOne [] = [countFirst];+ upOne (a:r) = case countMaybeNext (Just a) of+ {+ Just a' -> a':r;+ Nothing -> countFirst:a:r;+ };+ };+ };+}
+ src/Data/Empty.hs view
@@ -0,0 +1,63 @@+module Data.Empty where+{+ import Data.Countable;+ import Data.Searchable;++ class (Finite n) => Empty n where+ {+ never :: n -> a;+ never n = seq n undefined;+ };++ instance (Empty a,Empty b) => Empty (Either a b) where+ {+ never (Left a) = never a;+ never (Right a) = never a;+ };++ instance (Empty a,Finite b) => Empty (a,b) where+ {+ never (a,_) = never a;+ };++ instance (AtLeastOneCountable a,Finite a,Empty b) => Empty (a -> b) where+ {+ never ab = never (ab countFirst);+ };++ data Nothing;++ instance Countable Nothing where+ {+ countPrevious = never;+ countMaybeNext Nothing = Nothing;+ countMaybeNext (Just n) = never n;+ };++ instance Searchable Nothing where+ {+ search = finiteSearch;+ };++ instance Finite Nothing where+ {+ allValues = [];+ };++ instance Empty Nothing;++ instance Eq Nothing where+ {+ a == _b = never a;+ };++ instance Ord Nothing where+ {+ a <= _b = never a;+ };++ instance Show Nothing where+ {+ show a = never a;+ };+}
+ src/Data/Searchable.hs view
@@ -0,0 +1,342 @@+{-# OPTIONS -fno-warn-orphans #-}+-- | This module also includes these orphan instances:+--+-- * @('Searchable' a,'Eq' b) => 'Eq' (a -> b)@ / /+--+-- * @('Finite' t) => 'Foldable' ((->) t)@ / /+--+-- * @('Finite' a) => 'Traversable' ((->) a)@ / /+--+-- * @('Show' a,'Finite' a,'Show' b) => 'Show' (a -> b)@ / /+module Data.Searchable+(+ Searchable(..),forsome,forevery,+ Finite(..),finiteSearch,finiteCountPrevious,finiteCountMaybeNext+) where+{+ import Data.Countable;+ import Data.Monoid;+ import Data.Maybe;+ import Data.List;+ import Control.Applicative;+ import Data.Foldable hiding (find);+ import Data.Traversable;+ import Data.Word;+ import Data.Int;+ import Prelude;++ -- | It turns out there are 'Searchable' instances that are not 'Finite'.+ -- The @(c -> s)@ instance is based on the algorithm at+ -- <http://math.andrej.com/2007/09/28/seemingly-impossible-functional-programs/>.+ ;+ class Searchable a where+ {+ search :: (a -> Maybe b) -> Maybe b;+ };++ forsome :: (Searchable a) => (a -> Bool) -> Bool;+ forsome = isJust . search . (\ab a -> if ab a then Just () else Nothing);++ forevery :: (Searchable a) => (a -> Bool) -> Bool;+ forevery p = not (forsome (not . p));++ instance (Searchable a) => Searchable (Maybe a) where+ {+ search mamb = case mamb Nothing of+ {+ Just b -> Just b;+ Nothing -> search (mamb . Just);+ };+ };++ instance (Searchable a,Searchable b) => Searchable (Either a b) where+ {+ search eabb = case search (eabb . Left) of+ {+ Just b -> Just b;+ _ -> search (eabb . Right);+ }+ };++ instance (Searchable a,Searchable b) => Searchable (a,b) where+ {+ search abb = search (\a -> search (\b -> abb (a,b)));+ };++ instance (Countable c,Searchable s) => Searchable (c -> s) where+ {+ search csmx = case search Just of+ {+ Just def -> let+ {+ -- prepend :: s -> (c -> s) -> c -> s;+ prepend s cs c = case countPrevious c of+ {+ Just c' -> cs c';+ Nothing -> s;+ };++ -- findcs :: ((c -> s) -> Maybe x) -> c -> s;+ findcs csm = let+ {+ mx = search (\s' -> do+ {+ _ <- search (csm . (prepend s'));+ return s';+ });+ s = case mx of+ {+ Just s' -> s';+ _ -> def;+ };+ } in prepend s (findcs (csm . (prepend s)));+ } in csmx (findcs csmx);+ Nothing -> Nothing;+ };+ };++ instance (Searchable a,Eq b) => Eq (a -> b) where+ {+ p == q = forevery (\a -> p a == q a);+ };++ class (Searchable a,Countable a) => Finite a where+ {+ -- | Not necessarily in counting order.+ ;+ allValues :: [a];++ assemble :: (Applicative f) => (a -> f b) -> f (a -> b);+ assemble afb = fmap listLookup (traverse (\a -> fmap (\b -> (a,b)) (afb a)) allValues) where+ {+ -- listLookup :: [(a,b)] -> a -> b;+ listLookup [] _ = error "missing value"; -- this should never happen+ listLookup ((a,b):_) a' | a == a' = b;+ listLookup (_:l) a' = listLookup l a';+ };+ };++ instance (Finite t) => Foldable ((->) t) where+ {+ foldMap am ta = mconcat (fmap (am . ta) allValues);+ };++ instance (Finite a) => Traversable ((->) a) where+ {+ sequenceA = assemble;+ };++ firstJust :: [Maybe a] -> Maybe a;+ firstJust [] = Nothing;+ firstJust ((Just a):_) = Just a;+ firstJust (Nothing:mas) = firstJust mas;++ finiteSearch :: (Finite a) => (a -> Maybe b) -> Maybe b;+ finiteSearch p = firstJust (fmap p allValues);++ finiteCountPrevious :: (Finite a) => a -> Maybe a;+ finiteCountPrevious x = findp Nothing allValues where+ {+ findp ma (a:_) | a == x = ma;+ findp _ (a:as) = findp (Just a) as;+ findp _ [] = seq x (error "missing value");+ };++ firstItem :: [a] -> Maybe a;+ firstItem [] = Nothing;+ firstItem (a:_) = Just a;++ finiteCountMaybeNext :: (Finite a) => Maybe a -> Maybe a;+ finiteCountMaybeNext Nothing = firstItem allValues;+ finiteCountMaybeNext (Just x) = findmn allValues where+ {+ findmn (a:as) | x == a = firstItem as;+ findmn (_:as) = findmn as;+ findmn [] = seq x (error "missing value");+ };++ instance Searchable () where+ {+ search = finiteSearch;+ };++ instance Finite () where+ {+ allValues = [()];+ assemble afb = liftA (\v _ -> v) (afb ());+ };++ instance Searchable Bool where+ {+ search = finiteSearch;+ };++ instance Finite Bool where+ {+ allValues = [False,True];+ assemble afb = liftA2 (\f t x -> if x then t else f) (afb False) (afb True);+ };++ instance Searchable Word8 where+ {+ search = finiteSearch;+ };++ instance Finite Word8 where+ {+ allValues = enumFrom minBound;+ };++ instance Searchable Word16 where+ {+ search = finiteSearch;+ };++ instance Finite Word16 where+ {+ allValues = enumFrom minBound;+ };++ instance Searchable Word32 where+ {+ search = finiteSearch;+ };++ instance Finite Word32 where+ {+ allValues = enumFrom minBound;+ };++ instance Searchable Word64 where+ {+ search = finiteSearch;+ };++ instance Finite Word64 where+ {+ allValues = enumFrom minBound;+ };++ instance Searchable Int8 where+ {+ search = finiteSearch;+ };++ instance Finite Int8 where+ {+ allValues = enumFrom minBound;+ };++ instance Searchable Int16 where+ {+ search = finiteSearch;+ };++ instance Finite Int16 where+ {+ allValues = enumFrom minBound;+ };++ instance Searchable Int32 where+ {+ search = finiteSearch;+ };++ instance Finite Int32 where+ {+ allValues = enumFrom minBound;+ };++ instance Searchable Int64 where+ {+ search = finiteSearch;+ };++ instance Finite Int64 where+ {+ allValues = enumFrom minBound;+ };++ instance (Finite a) => Finite (Maybe a) where+ {+ allValues = Nothing:(fmap Just allValues);+ };++ instance (Finite a,Finite b) => Finite (Either a b) where+ {+ allValues = (fmap Left allValues) ++ (fmap Right allValues);+ };++ instance (Finite a,Finite b) => Finite (a,b) where+ {+ allValues = liftA2 (,) allValues allValues;+ };++ setpair :: (Eq a) => (a,b) -> (a -> b) -> (a -> b);+ setpair (a',b') _ a | a == a' = b';+ setpair _ ab a = ab a;++ data IsoCountable x = forall l. (Countable l) => MkIsoCountable (x -> l) (l -> x);++ isoCountableFn :: (Finite a,Countable b) => IsoCountable (a -> b);+ isoCountableFn = makeFromList allValues where+ {+ makeFromList :: (Eq a,Countable b) => [a] -> IsoCountable (a -> b);+ makeFromList [] = MkIsoCountable (\_ -> ()) (\a -> seq a undefined);+ makeFromList (a:as) = case makeFromList as of+ {+ MkIsoCountable encode decode ->+ MkIsoCountable (\ab -> (ab a,encode ab)) (\(b,l) -> setpair (a,b) (decode l));+ };+ };++ instance (Finite a,Countable b) => Countable (a -> b) where+ {+ countPrevious = case isoCountableFn of+ {+ MkIsoCountable encode decode -> (fmap decode) . countPrevious . encode;+ };+ countMaybeNext = case isoCountableFn of+ {+ MkIsoCountable encode decode -> (fmap decode) . countMaybeNext . (fmap encode);+ };+ };++ instance (Finite a,AtLeastOneCountable b) => AtLeastOneCountable (a -> b) where+ {+ countFirst = \_ -> countFirst;+ };++ data IsoInfiniteCountable x = forall l. (InfiniteCountable l) => MkIsoInfiniteCountable (x -> l) (l -> x);++ isoInfiniteCountableFn :: (Finite a,AtLeastOneCountable a,InfiniteCountable b) => IsoInfiniteCountable (a -> b);+ isoInfiniteCountableFn = makeFromList allValues where+ {+ makeFromList :: (Eq a,InfiniteCountable b) => [a] -> IsoInfiniteCountable (a -> b);+ makeFromList [] = undefined;+ makeFromList [a] = MkIsoInfiniteCountable (\ab -> ab a) (\b -> setpair (a,b) (\a' -> seq a' undefined));+ makeFromList (a:as) = case makeFromList as of+ {+ MkIsoInfiniteCountable encode decode ->+ MkIsoInfiniteCountable (\ab -> (ab a,encode ab)) (\(b,l) -> setpair (a,b) (decode l));+ };+ };++ instance (Finite a,AtLeastOneCountable a,InfiniteCountable b) => InfiniteCountable (a -> b) where+ {+ countNext = case isoInfiniteCountableFn of+ {+ MkIsoInfiniteCountable encode decode -> decode . countNext . (fmap encode);+ };+ };++ instance (Finite a,Finite b) => Finite (a -> b) where+ {+ allValues = sequenceA (\_ -> allValues);+ };++ instance (Show a,Finite a,Show b) => Show (a -> b) where+ {+ show f = "{" ++ (intercalate "," (fmap (\a -> (show a) ++ "->" ++ (show (f a))) allValues)) ++ "}";+ };+}