@@ -1,6 +1,6 @@
1{-# LANGUAGE GADTs, TypeFamilies, TypeOperators, ScopedTypeVariables, CPP #-}
1{-# LANGUAGE GADTs, TypeFamilies, TypeOperators, ScopedTypeVariables, CPP #-}
2{-# LANGUAGE StandaloneDeriving, FlexibleInstances #-}
2{-# LANGUAGE StandaloneDeriving, FlexibleInstances #-}
3−{-# LANGUAGE DefaultSignatures, FlexibleContexts, LambdaCase #-}
3+{-# LANGUAGE DefaultSignatures, FlexibleContexts, EmptyCase, LambdaCase #-}
4{-# OPTIONS_GHC -Wall -fenable-rewrite-rules #-}
4{-# OPTIONS_GHC -Wall -fenable-rewrite-rules #-}
6-- ScopedTypeVariables works around a 6.10 bug. The forall keyword is
6-- ScopedTypeVariables works around a 6.10 bug. The forall keyword is
@@ -9,7 +9,7 @@
9----------------------------------------------------------------------
9----------------------------------------------------------------------
11-- Module : Data.MemoTrie
11-- Module : Data.MemoTrie
12−-- Copyright : (c) Conal Elliott 2008-2016
12+-- Copyright : (c) Conal Elliott 2008-2012
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,29 +55,21 @@ 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
62-- Export the parts of HasTrie separately in order to get the associated data
61-- Export the parts of HasTrie separately in order to get the associated data
63-- type constructors, so I can define instances of other classes on them.
62-- type constructors, so I can define instances of other classes on them.
65−import Data.Function (fix)
66import Data.Bits
64import Data.Bits
67import Data.Word
65import Data.Word
68import Data.Int
66import Data.Int
69−#if !MIN_VERSION_base(4,8,0)
70import Control.Applicative
67import Control.Applicative
72import Control.Arrow (first,(&&&))
68import Control.Arrow (first,(&&&))
73−#if !MIN_VERSION_base(4,8,0)
74import Data.Monoid
69import Data.Monoid
76import Data.Function (on)
70import Data.Function (on)
77import GHC.Generics
71import GHC.Generics
79−import Control.Newtype.Generics
81import Data.Void (Void)
73import Data.Void (Void)
83-- import Prelude hiding (id,(.))
75-- import Prelude hiding (id,(.))
@@ -136,13 +128,7 @@ untrie3 tt = untrie2 . untrie tt
139−-- {-# RULES "trie/untrie" forall t. trie (untrie t) = t #-}
131+{-# RULES "trie/untrie" forall t. trie (untrie t) = t #-}
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
147-- Don't include the dual rule:
133-- Don't include the dual rule:
148-- "untrie/trie" forall f. untrie (trie f) = f
134-- "untrie/trie" forall f. untrie (trie f) = f
@@ -170,42 +156,6 @@ mup mem f = memo (mem . f)
170memo2 = mup memo
156memo2 = mup memo
171memo3 = mup memo2
157memo3 = 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
209-- | Apply a unary function inside of a trie
159-- | Apply a unary function inside of a trie
210inTrie :: (HasTrie a, HasTrie c) =>
160inTrie :: (HasTrie a, HasTrie c) =>
211 ((a -> b) -> (c -> d))
161 ((a -> b) -> (c -> d))
@@ -229,28 +179,17 @@ inTrie3 = untrie ~> inTrie2
230instance HasTrie Void where
180instance HasTrie Void where
231 -- As suggested by Audun Skaugen
181 -- As suggested by Audun Skaugen
232− data Void :->: a = VoidTrie
182+ data Void :->: a = VoidTrie
233 trie _ = VoidTrie
183 trie _ = VoidTrie
234− untrie VoidTrie = \ _ -> error "untrie VoidTrie"
184+ untrie VoidTrie = \case
235− -- \case -- needs EmptyCase
236 enumerate VoidTrie = []
185 enumerate VoidTrie = []
238−instance Newtype (Void :->: a) where
239− type O (Void :->: a) = ()
241− unpack VoidTrie = ()
243instance HasTrie () where
187instance HasTrie () where
244 newtype () :->: a = UnitTrie a
188 newtype () :->: a = UnitTrie a
245 trie f = UnitTrie (f ())
189 trie f = UnitTrie (f ())
246 untrie (UnitTrie a) = \ () -> a
190 untrie (UnitTrie a) = \ () -> a
247 enumerate (UnitTrie a) = [((),a)]
191 enumerate (UnitTrie a) = [((),a)]
249−instance Newtype (() :->: a) where
250− type O (() :->: a) = a
252− unpack (UnitTrie a) = a
254-- Proofs of inverse properties:
193-- Proofs of inverse properties:
@@ -286,11 +225,6 @@ instance HasTrie Bool where
286 untrie (BoolTrie f t) = if' f t
225 untrie (BoolTrie f t) = if' f t
287 enumerate (BoolTrie f t) = [(False,f),(True,t)]
226 enumerate (BoolTrie f t) = [(False,f),(True,t)]
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')
294-- | Conditional with boolean last.
228-- | Conditional with boolean last.
295-- Spec: @if' (f False) (f True) == f@
229-- Spec: @if' (f False) (f True) == f@
296if' :: x -> x -> Bool -> x
230if' :: x -> x -> Bool -> x
@@ -315,16 +249,6 @@ if' _ e True = e
315 BoolTrie f t
249 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)
329instance (HasTrie a, HasTrie b) => HasTrie (Either a b) where
253instance (HasTrie a, HasTrie b) => HasTrie (Either a b) where
330 data (Either a b) :->: x = EitherTrie (a :->: x) (b :->: x)
254 data (Either a b) :->: x = EitherTrie (a :->: x) (b :->: x)
@@ -332,11 +256,6 @@ instance (HasTrie a, HasTrie b) => HasTrie (Either a b) where
332 untrie (EitherTrie s t) = either (untrie s) (untrie t)
256 untrie (EitherTrie s t) = either (untrie s) (untrie t)
333 enumerate (EitherTrie s t) = enum' Left s `weave` enum' Right t
257 enumerate (EitherTrie s t) = enum' Left s `weave` enum' Right t
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)
340enum' :: (HasTrie a) => (a -> a') -> (a :->: b) -> [(a', b)]
259enum' :: (HasTrie a) => (a -> a') -> (a :->: b) -> [(a', b)]
341enum' f = (fmap.first) f . enumerate
260enum' f = (fmap.first) f . enumerate
@@ -376,11 +295,6 @@ instance (HasTrie a, HasTrie b) => HasTrie (a,b) where
376 enumerate (PairTrie tt) =
295 enumerate (PairTrie tt) =
377 [ ((a,b),x) | (a,t) <- enumerate tt , (b,x) <- enumerate t ]
296 [ ((a,b),x) | (a,t) <- enumerate tt , (b,x) <- enumerate t ]
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
385 untrie (trie f)
299 untrie (trie f)
386 == { trie def }
300 == { trie def }
@@ -587,12 +501,7 @@ instance HasTrie a => Monad ((:->:) a) where
588instance (HasTrie a, Monoid b) => Monoid (a :->: b) where
502instance (HasTrie a, Monoid b) => Monoid (a :->: b) where
589 mempty = trie mempty
503 mempty = trie mempty
590−#if !MIN_VERSION_base(4,11,0)
591 mappend = inTrie2 mappend
504 mappend = inTrie2 mappend
593−instance (HasTrie a, Semigroup b) => Semigroup (a :->: b) where
597instance HasTrie a => Functor ((:->:) a) where
506instance HasTrie a => Functor ((:->:) a) where
598 fmap f = inTrie (fmap f)
507 fmap f = inTrie (fmap f)
@@ -654,8 +563,7 @@ f1' = memo f1
654instance HasTrie (V1 x) where
563instance HasTrie (V1 x) where
655 data (V1 x :->: b) = V1Trie
564 data (V1 x :->: b) = V1Trie
656 trie _ = V1Trie
565 trie _ = V1Trie
657− untrie V1Trie = \ _ -> error "untrie V1Trie"
566+ untrie V1Trie = \case
658− -- \case -- needs EmptyCase
659 enumerate V1Trie = []
567 enumerate V1Trie = []
661-- | just like @()@
569-- | just like @()@
@@ -697,7 +605,6 @@ instance (HasTrie (f x)) => HasTrie (M1 i t f x) where
697-- "unlifted" generic representation. (i.e. is a unary type constructor).
605-- "unlifted" generic representation. (i.e. is a unary type constructor).
698type Reg a = Rep a ()
606type Reg a = Rep a ()
700−-- | 'Generic'-friendly default for 'trie'
701trieGeneric :: (Generic a, HasTrie (Reg a))
608trieGeneric :: (Generic a, HasTrie (Reg a))
702 => ((Reg a :->: b) -> (a :->: b))
609 => ((Reg a :->: b) -> (a :->: b))
703 -> (a -> b)
610 -> (a -> b)
@@ -705,7 +612,6 @@ trieGeneric :: (Generic a, HasTrie (Reg a))
705trieGeneric theConstructor f = theConstructor (trie (f . to))
612trieGeneric theConstructor f = theConstructor (trie (f . to))
706{-# INLINEABLE trieGeneric #-}
613{-# INLINEABLE trieGeneric #-}
708−-- | 'Generic'-friendly default for 'untrie'
709untrieGeneric :: (Generic a, HasTrie (Reg a))
615untrieGeneric :: (Generic a, HasTrie (Reg a))
710 => ((a :->: b) -> (Reg a :->: b))
616 => ((a :->: b) -> (Reg a :->: b))
711 -> (a :->: b)
617 -> (a :->: b)
@@ -713,7 +619,6 @@ untrieGeneric :: (Generic a, HasTrie (Reg a))
713untrieGeneric theDestructor t = \a -> (untrie (theDestructor t)) (from a)
619untrieGeneric theDestructor t = \a -> (untrie (theDestructor t)) (from a)
714{-# INLINEABLE untrieGeneric #-}
620{-# INLINEABLE untrieGeneric #-}
716−-- | 'Generic'-friendly default for 'enumerate'
717enumerateGeneric :: (Generic a, HasTrie (Reg a))
622enumerateGeneric :: (Generic a, HasTrie (Reg a))
718 => ((a :->: b) -> (Reg a :->: b))
623 => ((a :->: b) -> (Reg a :->: b))
719 -> (a :->: b)
624 -> (a :->: b)
@@ -738,3 +643,4 @@ dropSum s = case s of
738liftSum :: Either (f a) (g a) -> (f :+: g) a
643liftSum :: Either (f a) (g a) -> (f :+: g) a
739liftSum = either L1 R1
644liftSum = either L1 R1
740{-# INLINEABLE liftSum #-}
645{-# INLINEABLE liftSum #-}