@@ -9,7 +9,7 @@
9----------------------------------------------------------------------
9----------------------------------------------------------------------
11-- Module : Data.MemoTrie
11-- Module : Data.MemoTrie
12−-- Copyright : (c) Conal Elliott 2008-2012
12+-- Copyright : (c) Conal Elliott 2008-2016
13-- License : BSD3
13-- License : BSD3
15-- Maintainer : conal@conal.net
15-- Maintainer : conal@conal.net
@@ -42,7 +42,7 @@
42-- see @examples/Generic.hs@, which can be run with:
42-- see @examples/Generic.hs@, which can be run with:
45−-- $ cabal configure -fexamples && cabal run generic
45+-- cabal configure -fexamples && cabal run generic
@@ -55,22 +55,28 @@ module Data.MemoTrie
55 , memo, memo2, memo3, mup
55 , memo, memo2, memo3, mup
56 , inTrie, inTrie2, inTrie3
56 , inTrie, inTrie2, inTrie3
57 -- , untrieBits
57 -- , untrieBits
58− , trieGeneric, untrieGeneric, enumerateGeneric, Reg
58+ , trieGeneric, untrieGeneric, enumerateGeneric, Reg
61-- Export the parts of HasTrie separately in order to get the associated data
62-- Export the parts of HasTrie separately in order to get the associated data
62-- type constructors, so I can define instances of other classes on them.
63-- type constructors, so I can define instances of other classes on them.
65+import Data.Function (fix)
64import Data.Bits
66import Data.Bits
65import Data.Word
67import Data.Word
66import Data.Int
68import Data.Int
69+#if !MIN_VERSION_base(4,8,0)
67−-- import Control.Applicative
70+import Control.Applicative
68import Control.Arrow (first,(&&&))
72import Control.Arrow (first,(&&&))
73+#if !MIN_VERSION_base(4,8,0)
69−-- import Data.Monoid
74+import Data.Monoid
70import Data.Function (on)
76import Data.Function (on)
71import GHC.Generics
77import GHC.Generics
73−import Control.Newtype
79+import Control.Newtype.Generics
75import Data.Void (Void)
81import Data.Void (Void)
@@ -164,6 +170,42 @@ mup mem f = memo (mem . f)
164memo2 = mup memo
170memo2 = mup memo
165memo3 = mup memo2
171memo3 = mup memo2
173+-- | Memoizing recursion. Use like `fix`.
174+memoFix :: HasTrie a => ((a -> b) -> (a -> b)) -> (a -> b)
175+memoFix h = fix (memo . h)
180+memoFix h = fix (\ f' -> memo (h f'))
183+ where f' = memo (h f')
194+fibF :: (Integer -> Integer) -> (Integer -> Integer)
197+fibF f n = f (n-1) + f (n-2)
199+fib :: Integer -> Integer
202+fib' :: Integer -> Integer
205+-- Try fib 30 vs fib' 30
167-- | Apply a unary function inside of a trie
209-- | Apply a unary function inside of a trie
168inTrie :: (HasTrie a, HasTrie c) =>
210inTrie :: (HasTrie a, HasTrie c) =>
169 ((a -> b) -> (c -> d))
211 ((a -> b) -> (c -> d))
@@ -273,6 +315,16 @@ if' _ e True = e
273 BoolTrie f t
315 BoolTrie f t
318+instance HasTrie a => HasTrie (Maybe a) where
319+ data (:->:) (Maybe a) b = MaybeTrie b (a :->: b)
320+ trie f = MaybeTrie (f Nothing) (trie (f . Just))
321+ untrie (MaybeTrie nothing_val a_trie) = maybe nothing_val (untrie a_trie)
322+ enumerate (MaybeTrie nothing_val a_trie) = (Nothing, nothing_val) : enum' Just a_trie
324+instance Newtype (Maybe a :->: x) where
325+ type O (Maybe a :->: x) = (x, a :->: x)
326+ pack (a,f) = MaybeTrie a f
327+ unpack (MaybeTrie a f) = (a,f)
277instance (HasTrie a, HasTrie b) => HasTrie (Either a b) where
329instance (HasTrie a, HasTrie b) => HasTrie (Either a b) where
278 data (Either a b) :->: x = EitherTrie (a :->: x) (b :->: x)
330 data (Either a b) :->: x = EitherTrie (a :->: x) (b :->: x)
@@ -535,7 +587,12 @@ instance HasTrie a => Monad ((:->:) a) where
536instance (HasTrie a, Monoid b) => Monoid (a :->: b) where
588instance (HasTrie a, Monoid b) => Monoid (a :->: b) where
537 mempty = trie mempty
589 mempty = trie mempty
590+#if !MIN_VERSION_base(4,11,0)
538 mappend = inTrie2 mappend
591 mappend = inTrie2 mappend
593+instance (HasTrie a, Semigroup b) => Semigroup (a :->: b) where
540instance HasTrie a => Functor ((:->:) a) where
597instance HasTrie a => Functor ((:->:) a) where
541 fmap f = inTrie (fmap f)
598 fmap f = inTrie (fmap f)
@@ -640,6 +697,7 @@ instance (HasTrie (f x)) => HasTrie (M1 i t f x) where
640-- "unlifted" generic representation. (i.e. is a unary type constructor).
697-- "unlifted" generic representation. (i.e. is a unary type constructor).
641type Reg a = Rep a ()
698type Reg a = Rep a ()
700+-- | 'Generic'-friendly default for 'trie'
643trieGeneric :: (Generic a, HasTrie (Reg a))
701trieGeneric :: (Generic a, HasTrie (Reg a))
644 => ((Reg a :->: b) -> (a :->: b))
702 => ((Reg a :->: b) -> (a :->: b))
645 -> (a -> b)
703 -> (a -> b)
@@ -647,6 +705,7 @@ trieGeneric :: (Generic a, HasTrie (Reg a))
647trieGeneric theConstructor f = theConstructor (trie (f . to))
705trieGeneric theConstructor f = theConstructor (trie (f . to))
648{-# INLINEABLE trieGeneric #-}
706{-# INLINEABLE trieGeneric #-}
708+-- | 'Generic'-friendly default for 'untrie'
650untrieGeneric :: (Generic a, HasTrie (Reg a))
709untrieGeneric :: (Generic a, HasTrie (Reg a))
651 => ((a :->: b) -> (Reg a :->: b))
710 => ((a :->: b) -> (Reg a :->: b))
652 -> (a :->: b)
711 -> (a :->: b)
@@ -654,6 +713,7 @@ untrieGeneric :: (Generic a, HasTrie (Reg a))
654untrieGeneric theDestructor t = \a -> (untrie (theDestructor t)) (from a)
713untrieGeneric theDestructor t = \a -> (untrie (theDestructor t)) (from a)
655{-# INLINEABLE untrieGeneric #-}
714{-# INLINEABLE untrieGeneric #-}
716+-- | 'Generic'-friendly default for 'enumerate'
657enumerateGeneric :: (Generic a, HasTrie (Reg a))
717enumerateGeneric :: (Generic a, HasTrie (Reg a))
658 => ((a :->: b) -> (Reg a :->: b))
718 => ((a :->: b) -> (Reg a :->: b))
659 -> (a :->: b)
719 -> (a :->: b)
@@ -678,4 +738,3 @@ dropSum s = case s of
678liftSum :: Either (f a) (g a) -> (f :+: g) a
738liftSum :: Either (f a) (g a) -> (f :+: g) a
679liftSum = either L1 R1
739liftSum = either L1 R1
680{-# INLINEABLE liftSum #-}
740{-# INLINEABLE liftSum #-}