@@ -1,14 +1,15 @@
11{-# LANGUAGE GADTs, TypeFamilies, TypeOperators, ScopedTypeVariables, CPP #-}
22{-# LANGUAGE StandaloneDeriving, FlexibleInstances #-}
3−{-# LANGUAGE DefaultSignatures, FlexibleContexts, EmptyCase, LambdaCase #-}
3+{-# LANGUAGE DefaultSignatures, FlexibleContexts, LambdaCase #-}
44{-# OPTIONS_GHC -Wall -fenable-rewrite-rules #-}
5+
56-- ScopedTypeVariables works around a 6.10 bug. The forall keyword is
67-- supposed to be recognized in a RULES pragma.
78
89----------------------------------------------------------------------
910-- |
1011-- Module : Data.MemoTrie
11−-- Copyright : (c) Conal Elliott 2008-2012
12+-- Copyright : (c) Conal Elliott 2008-2016
1213-- License : BSD3
1314--
1415-- Maintainer : conal@conal.net
@@ -16,33 +17,32 @@
1617--
1718-- Trie-based memoizer
1819--
19−-- Adapted from sjanssen's paste: \"a lazy trie\" <http://hpaste.org/3839>,
20+-- Adapted from sjanssen's paste: <http://hpaste.org/3839 \"a lazy trie\">,
2021-- which I think is based on Ralf Hinze's paper "Memo Functions,
2122-- Polytypically!".
2223--
2324-- You can automatically derive generic instances. for example:
2425--
2526-- @
26−-- -- LANGUAGE <https://ocharles.org.uk/blog/posts/2014-12-16-derive-generic.html DeriveGeneric>, TypeOperators, TypeFamilies #-}
27+-- {-# LANGUAGE <https://ocharles.org.uk/blog/posts/2014-12-16-derive-generic.html DeriveGeneric>, TypeOperators, TypeFamilies #-}
2728-- import Data.MemoTrie
2829-- import GHC.Generics (Generic)
2930--
30−-- data Color
31−-- = RGB Int Int Int
32−-- | Color String
31+-- data Color = RGB Int Int Int
32+-- | NamedColor String
3333-- deriving ('Generic')
3434--
3535-- instance HasTrie Color where
36−-- newtype (Color :->: b) = ColorTrie { unColorTrie :: 'Reg' Color :->: b }
37−-- trie = 'trieGeneric' ColorTrie
38−-- untrie = 'untrieGeneric' unColorTrie
39−-- enumerate = 'enumerateGeneric' unColorTrie
36+-- newtype (Color :->: b) = ColorTrie { unColorTrie :: 'Reg' Color :->: b }
37+-- trie = 'trieGeneric' ColorTrie
38+-- untrie = 'untrieGeneric' unColorTrie
39+-- enumerate = 'enumerateGeneric' unColorTrie
4040-- @
4141--
4242-- see @examples/Generic.hs@, which can be run with:
4343--
4444-- @
45−-- $ cabal configure -fexamples && cabal run generic
45+-- cabal configure -fexamples && cabal run generic
4646-- @
4747--
4848--
@@ -55,21 +55,29 @@ module Data.MemoTrie
5555 , memo, memo2, memo3, mup
5656 , inTrie, inTrie2, inTrie3
5757 -- , untrieBits
58− , trieGeneric, untrieGeneric, enumerateGeneric, Reg
58+ , trieGeneric, untrieGeneric, enumerateGeneric, Reg
59+ , memoFix
5960 ) where
6061
6162-- Export the parts of HasTrie separately in order to get the associated data
6263-- type constructors, so I can define instances of other classes on them.
6364
65+import Data.Function (fix)
6466import Data.Bits
6567import Data.Word
6668import Data.Int
69+#if !MIN_VERSION_base(4,8,0)
6770import Control.Applicative
71+#endif
6872import Control.Arrow (first,(&&&))
73+#if !MIN_VERSION_base(4,8,0)
6974import Data.Monoid
75+#endif
7076import Data.Function (on)
7177import GHC.Generics
7278
79+import Control.Newtype.Generics
80+
7381import Data.Void (Void)
7482
7583-- import Prelude hiding (id,(.))
@@ -128,7 +136,13 @@ untrie3 tt = untrie2 . untrie tt
128136-}
129137
130138
131−{-# RULES "trie/untrie" forall t. trie (untrie t) = t #-}
139+-- {-# RULES "trie/untrie" forall t. trie (untrie t) = t #-}
140+
141+-- warning: [-Winline-rule-shadowing] …
142+-- Rule "trie/untrie" may never fire
143+-- because rule "Class op untrie" for ‘untrie’ might fire first
144+-- Probable fix: add phase [n] or [~n] to the competing rule
145+
132146
133147-- Don't include the dual rule:
134148-- "untrie/trie" forall f. untrie (trie f) = f
@@ -156,6 +170,42 @@ mup mem f = memo (mem . f)
156170memo2 = mup memo
157171memo3 = mup memo2
158172
173+-- | Memoizing recursion. Use like `fix`.
174+memoFix :: HasTrie a => ((a -> b) -> (a -> b)) -> (a -> b)
175+memoFix h = fix (memo . h)
176+
177+#if 0
178+-- Equivalently,
179+
180+memoFix h = fix (\ f' -> memo (h f'))
181+
182+memoFix h = f'
183+ where f' = memo (h f')
184+
185+memoFix h = f'
186+ where
187+ f' = memo f
188+ f = h f'
189+#endif
190+
191+#if 0
192+-- Example
193+
194+fibF :: (Integer -> Integer) -> (Integer -> Integer)
195+fibF _ 0 = 1
196+fibF _ 1 = 1
197+fibF f n = f (n-1) + f (n-2)
198+
199+fib :: Integer -> Integer
200+fib = fix fibF
201+
202+fib' :: Integer -> Integer
203+fib' = memoFix fibF
204+
205+-- Try fib 30 vs fib' 30
206+#endif
207+
208+
159209-- | Apply a unary function inside of a trie
160210inTrie :: (HasTrie a, HasTrie c) =>
161211 ((a -> b) -> (c -> d))
@@ -179,16 +229,27 @@ inTrie3 = untrie ~> inTrie2
179229
180230instance HasTrie Void where
181231 -- As suggested by Audun Skaugen
182− data Void :->: a = VoidTrie
232+ data Void :->: a = VoidTrie
183233 trie _ = VoidTrie
184− untrie VoidTrie = \case
234+ untrie VoidTrie = \ _ -> error "untrie VoidTrie"
235+ -- \case -- needs EmptyCase
185236 enumerate VoidTrie = []
186237
238+instance Newtype (Void :->: a) where
239+ type O (Void :->: a) = ()
240+ pack () = VoidTrie
241+ unpack VoidTrie = ()
242+
187243instance HasTrie () where
188− newtype () :->: a = UnitTrie a
189− trie f = UnitTrie (f ())
190− untrie (UnitTrie a) = \ () -> a
191− enumerate (UnitTrie a) = [((),a)]
244+ newtype () :->: a = UnitTrie a
245+ trie f = UnitTrie (f ())
246+ untrie (UnitTrie a) = \ () -> a
247+ enumerate (UnitTrie a) = [((),a)]
248+
249+instance Newtype (() :->: a) where
250+ type O (() :->: a) = a
251+ pack a = UnitTrie a
252+ unpack (UnitTrie a) = a
192253
193254-- Proofs of inverse properties:
194255
@@ -220,10 +281,15 @@ memoizing hyper-strict functions.
220281
221282
222283instance HasTrie Bool where
223− data Bool :->: x = BoolTrie x x
224− trie f = BoolTrie (f False) (f True)
225− untrie (BoolTrie f t) = if' f t
226− enumerate (BoolTrie f t) = [(False,f),(True,t)]
284+ data Bool :->: x = BoolTrie x x
285+ trie f = BoolTrie (f False) (f True)
286+ untrie (BoolTrie f t) = if' f t
287+ enumerate (BoolTrie f t) = [(False,f),(True,t)]
288+
289+instance Newtype (Bool :->: a) where
290+ type O (Bool :->: a) = (a,a)
291+ pack (a,a') = BoolTrie a a'
292+ unpack (BoolTrie a a') = (a,a')
227293
228294-- | Conditional with boolean last.
229295-- Spec: @if' (f False) (f True) == f@
@@ -249,12 +315,27 @@ if' _ e True = e
249315 BoolTrie f t
250316-}
251317
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
323+
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)
252328
253329instance (HasTrie a, HasTrie b) => HasTrie (Either a b) where
254− data (Either a b) :->: x = EitherTrie (a :->: x) (b :->: x)
255− trie f = EitherTrie (trie (f . Left)) (trie (f . Right))
256− untrie (EitherTrie s t) = either (untrie s) (untrie t)
257− enumerate (EitherTrie s t) = enum' Left s `weave` enum' Right t
330+ data (Either a b) :->: x = EitherTrie (a :->: x) (b :->: x)
331+ trie f = EitherTrie (trie (f . Left)) (trie (f . Right))
332+ untrie (EitherTrie s t) = either (untrie s) (untrie t)
333+ enumerate (EitherTrie s t) = enum' Left s `weave` enum' Right t
334+
335+instance Newtype (Either a b :->: x) where
336+ type O (Either a b :->: x) = (a :->: x, b :->: x)
337+ pack (f,g) = EitherTrie f g
338+ unpack (EitherTrie f g) = (f,g)
258339
259340enum' :: (HasTrie a) => (a -> a') -> (a :->: b) -> [(a', b)]
260341enum' f = (fmap.first) f . enumerate
@@ -289,11 +370,16 @@ as `weave` [] = as
289370
290371
291372instance (HasTrie a, HasTrie b) => HasTrie (a,b) where
292− newtype (a,b) :->: x = PairTrie (a :->: (b :->: x))
293− trie f = PairTrie (trie (trie . curry f))
294− untrie (PairTrie t) = uncurry (untrie . untrie t)
295− enumerate (PairTrie tt) =
296− [ ((a,b),x) | (a,t) <- enumerate tt , (b,x) <- enumerate t ]
373+ newtype (a,b) :->: x = PairTrie (a :->: (b :->: x))
374+ trie f = PairTrie (trie (trie . curry f))
375+ untrie (PairTrie t) = uncurry (untrie . untrie t)
376+ enumerate (PairTrie tt) =
377+ [ ((a,b),x) | (a,t) <- enumerate tt , (b,x) <- enumerate t ]
378+
379+instance Newtype ((a,b) :->: x) where
380+ type O ((a,b) :->: x) = a :->: b :->: x
381+ pack abx = PairTrie abx
382+ unpack (PairTrie abx) = abx
297383
298384{-
299385 untrie (trie f)
@@ -322,10 +408,10 @@ instance (HasTrie a, HasTrie b) => HasTrie (a,b) where
322408-}
323409
324410instance (HasTrie a, HasTrie b, HasTrie c) => HasTrie (a,b,c) where
325− newtype (a,b,c) :->: x = TripleTrie (((a,b),c) :->: x)
326− trie f = TripleTrie (trie (f . trip))
327− untrie (TripleTrie t) = untrie t . detrip
328− enumerate (TripleTrie t) = enum' trip t
411+ newtype (a,b,c) :->: x = TripleTrie (((a,b),c) :->: x)
412+ trie f = TripleTrie (trie (f . trip))
413+ untrie (TripleTrie t) = untrie t . detrip
414+ enumerate (TripleTrie t) = enum' trip t
329415
330416trip :: ((a,b),c) -> (a,b,c)
331417trip ((a,b),c) = (a,b,c)
@@ -335,10 +421,10 @@ detrip (a,b,c) = ((a,b),c)
335421
336422
337423instance HasTrie x => HasTrie [x] where
338− newtype [x] :->: a = ListTrie (Either () (x,[x]) :->: a)
339− trie f = ListTrie (trie (f . list))
340− untrie (ListTrie t) = untrie t . delist
341− enumerate (ListTrie t) = enum' list t
424+ newtype [x] :->: a = ListTrie (Either () (x,[x]) :->: a)
425+ trie f = ListTrie (trie (f . list))
426+ untrie (ListTrie t) = untrie t . delist
427+ enumerate (ListTrie t) = enum' list t
342428
343429list :: Either () (x,[x]) -> [x]
344430list = either (const []) (uncurry (:))
@@ -349,10 +435,10 @@ delist (x:xs) = Right (x,xs)
349435
350436#define WordInstance(Type,TrieType)\
351437instance HasTrie Type where \
352− newtype Type :->: a = TrieType ([Bool] :->: a);\
353− trie f = TrieType (trie (f . unbits));\
354− untrie (TrieType t) = untrie t . bits;\
355− enumerate (TrieType t) = enum' unbits t
438+ newtype Type :->: a = TrieType ([Bool] :->: a);\
439+ trie f = TrieType (trie (f . unbits));\
440+ untrie (TrieType t) = untrie t . bits;\
441+ enumerate (TrieType t) = enum' unbits t
356442
357443WordInstance(Word,WordTrie)
358444WordInstance(Word8,Word8Trie)
@@ -361,10 +447,10 @@ WordInstance(Word32,Word32Trie)
361447WordInstance(Word64,Word64Trie)
362448
363449-- instance HasTrie Word where
364−-- newtype Word :->: a = WordTrie ([Bool] :->: a)
365−-- trie f = WordTrie (trie (f . unbits))
366−-- untrie (WordTrie t) = untrie t . bits
367−-- enumerate (WordTrie t) = enum' unbits t
450+-- newtype Word :->: a = WordTrie ([Bool] :->: a)
451+-- trie f = WordTrie (trie (f . unbits))
452+-- untrie (WordTrie t) = untrie t . bits
453+-- enumerate (WordTrie t) = enum' unbits t
368454
369455
370456-- | Extract bits in little-endian order
@@ -383,10 +469,10 @@ unbits [] = 0
383469unbits (x:xs) = unbit x .|. shiftL (unbits xs) 1
384470
385471instance HasTrie Char where
386− newtype Char :->: a = CharTrie (Int :->: a)
387− untrie (CharTrie t) n = untrie t (fromEnum n)
388− trie f = CharTrie (trie (f . toEnum))
389− enumerate (CharTrie t) = enum' toEnum t
472+ newtype Char :->: a = CharTrie (Int :->: a)
473+ untrie (CharTrie t) n = untrie t (fromEnum n)
474+ trie f = CharTrie (trie (f . toEnum))
475+ enumerate (CharTrie t) = enum' toEnum t
390476
391477-- Although Int is a Bits instance, we can't use bits directly for
392478-- memoizing, because the "bits" function gives an infinite result, since
@@ -395,10 +481,10 @@ instance HasTrie Char where
395481
396482#define IntInstance(IntType,WordType,TrieType) \
397483instance HasTrie IntType where \
398− newtype IntType :->: a = TrieType (WordType :->: a); \
399− untrie (TrieType t) n = untrie t (fromIntegral n); \
400− trie f = TrieType (trie (f . fromIntegral)); \
401− enumerate (TrieType t) = enum' fromIntegral t
484+ newtype IntType :->: a = TrieType (WordType :->: a); \
485+ untrie (TrieType t) n = untrie t (fromIntegral n); \
486+ trie f = TrieType (trie (f . fromIntegral)); \
487+ enumerate (TrieType t) = enum' fromIntegral t
402488
403489IntInstance(Int,Word,IntTrie)
404490IntInstance(Int8,Word8,Int8Trie)
@@ -410,10 +496,10 @@ IntInstance(Int64,Word64,Int64Trie)
410496-- extract the sign bit.
411497
412498instance HasTrie Integer where
413− newtype Integer :->: a = IntegerTrie ((Bool,[Bool]) :->: a)
414− trie f = IntegerTrie (trie (f . unbitsZ))
415− untrie (IntegerTrie t) = untrie t . bitsZ
416− enumerate (IntegerTrie t) = enum' unbitsZ t
499+ newtype Integer :->: a = IntegerTrie ((Bool,[Bool]) :->: a)
500+ trie f = IntegerTrie (trie (f . unbitsZ))
501+ untrie (IntegerTrie t) = untrie t . bitsZ
502+ enumerate (IntegerTrie t) = enum' unbitsZ t
417503
418504
419505unbitsZ :: (Num n, Bits n) => (Bool,[Bool]) -> n
@@ -501,7 +587,12 @@ instance HasTrie a => Monad ((:->:) a) where
501587
502588instance (HasTrie a, Monoid b) => Monoid (a :->: b) where
503589 mempty = trie mempty
590+#if !MIN_VERSION_base(4,11,0)
504591 mappend = inTrie2 mappend
592+#else
593+instance (HasTrie a, Semigroup b) => Semigroup (a :->: b) where
594+ (<>) = inTrie2 (<>)
595+#endif
505596
506597instance HasTrie a => Functor ((:->:) a) where
507598 fmap f = inTrie (fmap f)
@@ -525,7 +616,6 @@ infixr 9 @.@
525616(@.@) = inTrie2 (.)
526617
527618
528−
529619-- instance Category (:->:) where
530620-- id = idTrie
531621-- (.) = (.:)
@@ -544,7 +634,6 @@ necessary but disallowed `HasTrie` constraints on the domain type.
544634
545635-}
546636
547−
548637---- To go elsewhere
549638
550639-- Matt Hellige's notation for @argument f . result g@.
@@ -563,71 +652,72 @@ f1' = memo f1
563652
564653-- | just like @void@
565654instance HasTrie (V1 x) where
566− data (V1 x :->: b) = V1Trie
567− trie _ = V1Trie
568− untrie V1Trie = \case
569− enumerate V1Trie = []
655+ data (V1 x :->: b) = V1Trie
656+ trie _ = V1Trie
657+ untrie V1Trie = \ _ -> error "untrie V1Trie"
658+ -- \case -- needs EmptyCase
659+ enumerate V1Trie = []
570660
571661-- | just like @()@
572662instance HasTrie (U1 x) where
573− data (U1 x :->: b) = U1Trie b
574− trie f = U1Trie (f U1)
575− untrie (U1Trie b) = \U1 -> b
576− enumerate (U1Trie b) = [(U1, b)]
663+ data (U1 x :->: b) = U1Trie b
664+ trie f = U1Trie (f U1)
665+ untrie (U1Trie b) = \U1 -> b
666+ enumerate (U1Trie b) = [(U1, b)]
577667
578668-- | wraps @Either (f x) (g x)@
579669instance (HasTrie (f x), HasTrie (g x)) => HasTrie ((f :+: g) x) where
580− newtype ((f :+: g) x :->: b) = EitherTrie1 (Either (f x) (g x) :->: b)
581− trie f = EitherTrie1 (trie (f . liftSum))
582− untrie (EitherTrie1 t) = (untrie t) . dropSum
583− enumerate (EitherTrie1 t) = enum' liftSum t
670+ newtype ((f :+: g) x :->: b) = EitherTrie1 (Either (f x) (g x) :->: b)
671+ trie f = EitherTrie1 (trie (f . liftSum))
672+ untrie (EitherTrie1 t) = (untrie t) . dropSum
673+ enumerate (EitherTrie1 t) = enum' liftSum t
584674
585675-- | wraps @(f x, g x)@
586676instance (HasTrie (f x), HasTrie (g x)) => HasTrie ((f :*: g) x) where
587− newtype ((f :*: g) x :->: b) = PairTrie1 ((f x, g x) :->: b)
588− trie f = PairTrie1 (trie (f . liftProduct))
589− untrie (PairTrie1 t) = (untrie t) . dropProduct
590− enumerate (PairTrie1 t) = enum' liftProduct t
677+ newtype ((f :*: g) x :->: b) = PairTrie1 ((f x, g x) :->: b)
678+ trie f = PairTrie1 (trie (f . liftProduct))
679+ untrie (PairTrie1 t) = (untrie t) . dropProduct
680+ enumerate (PairTrie1 t) = enum' liftProduct t
591681
592682-- | wraps @a@
593683instance (HasTrie a) => HasTrie (K1 i a x) where
594− data (K1 i a x :->: b) = K1Trie (a :->: b)
595− trie f = K1Trie (trie (f . K1))
596− untrie (K1Trie t) = \(K1 a) -> (untrie t) a
597− enumerate (K1Trie t) = enum' K1 t
684+ data (K1 i a x :->: b) = K1Trie (a :->: b)
685+ trie f = K1Trie (trie (f . K1))
686+ untrie (K1Trie t) = \(K1 a) -> (untrie t) a
687+ enumerate (K1Trie t) = enum' K1 t
598688
599689-- | wraps @f x@
600690instance (HasTrie (f x)) => HasTrie (M1 i t f x) where
601− data (M1 i t f x :->: b) = M1Trie (f x :->: b)
602− trie f = M1Trie (trie (f . M1))
603− untrie (M1Trie t) = \(M1 a) -> (untrie t) a
604− enumerate (M1Trie t) = enum' M1 t
691+ data (M1 i t f x :->: b) = M1Trie (f x :->: b)
692+ trie f = M1Trie (trie (f . M1))
693+ untrie (M1Trie t) = \(M1 a) -> (untrie t) a
694+ enumerate (M1Trie t) = enum' M1 t
605695
606696-- | the data type in a __reg__ular form.
607697-- "unlifted" generic representation. (i.e. is a unary type constructor).
608698type Reg a = Rep a ()
609699
610−trieGeneric
611− :: (Generic a, HasTrie (Reg a))
612− => ((Reg a :->: b) -> (a :->: b))
613− -> (a -> b)
614− -> (a :->: b)
700+-- | 'Generic'-friendly default for 'trie'
701+trieGeneric :: (Generic a, HasTrie (Reg a))
702+ => ((Reg a :->: b) -> (a :->: b))
703+ -> (a -> b)
704+ -> (a :->: b)
615705trieGeneric theConstructor f = theConstructor (trie (f . to))
616706{-# INLINEABLE trieGeneric #-}
617707
618−untrieGeneric
619− :: (Generic a, HasTrie (Reg a))
620− => ((a :->: b) -> (Reg a :->: b))
621− -> (a :->: b)
622− -> (a -> b)
708+-- | 'Generic'-friendly default for 'untrie'
709+untrieGeneric :: (Generic a, HasTrie (Reg a))
710+ => ((a :->: b) -> (Reg a :->: b))
711+ -> (a :->: b)
712+ -> (a -> b)
623713untrieGeneric theDestructor t = \a -> (untrie (theDestructor t)) (from a)
624714{-# INLINEABLE untrieGeneric #-}
625715
626−enumerateGeneric
627− :: (Generic a, HasTrie (Reg a))
628− => ((a :->: b) -> (Reg a :->: b))
629− -> (a :->: b)
630− -> [(a, b)]
716+-- | 'Generic'-friendly default for 'enumerate'
717+enumerateGeneric :: (Generic a, HasTrie (Reg a))
718+ => ((a :->: b) -> (Reg a :->: b))
719+ -> (a :->: b)
720+ -> [(a, b)]
631721enumerateGeneric theDestructor t = enum' to (theDestructor t)
632722{-# INLINEABLE enumerateGeneric #-}
633723
@@ -641,11 +731,10 @@ liftProduct (a, b) = (a :*: b)
641731
642732dropSum :: (f :+: g) a -> Either (f a) (g a)
643733dropSum s = case s of
644− L1 x -> Left x
645− R1 x -> Right x
734+ L1 x -> Left x
735+ R1 x -> Right x
646736{-# INLINEABLE dropSum #-}
647737
648738liftSum :: Either (f a) (g a) -> (f :+: g) a
649739liftSum = either L1 R1
650740{-# INLINEABLE liftSum #-}
651−