Advertisement
Guest User

Untitled

a guest
Dec 14th, 2018
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. {-# LANGUAGE BangPatterns #-}
  2. {-# LANGUAGE CPP #-}
  3. {-# LANGUAGE NoImplicitPrelude #-}
  4. {-# LANGUAGE KindSignatures #-}
  5. {-# LANGUAGE GADTSyntax #-}
  6. {-# LANGUAGE RankNTypes #-}
  7. {-# LANGUAGE ScopedTypeVariables #-}
  8.  
  9. {-# OPTIONS_GHC -Wall -Werror #-}
  10.  
  11. -- | This module defines an API centred around linked lists of unlifted values.
  12. module Data.List.Unlifted
  13.   ( UList(UNil,UCons)
  14.   , map
  15.   , foldr
  16.   , foldl
  17.   , foldl'
  18.  , null
  19.  , scanl
  20.  , filter
  21.  , length
  22.  , singleton
  23.  , pure
  24.  , cons
  25.  , traverse_
  26.  , concat
  27.  , concatMap
  28.  , foldMap
  29.  , foldlM
  30.  , foldrM
  31.  ) where
  32.  
  33. import qualified Control.Applicative as A
  34. import qualified Data.Foldable as F
  35. import Control.Monad (Monad(..))
  36. import Control.Category
  37. import GHC.Prim
  38. import GHC.Types
  39. import GHC.Magic (oneShot)
  40. -- import Data.Function (id)
  41. import Data.Semigroup (Semigroup((<>)))
  42. #if MIN_VERSION_base(4,9,0)
  43. import Data.Monoid (Monoid(mempty, mappend))
  44. #endif
  45. import GHC.Num ((+))
  46.  
  47. -- | A linked list of unlifted values. The values stored in the list
  48. --   are guaranteed to not be thunks.
  49. data UList (a :: TYPE 'UnliftedRep) where
  50.   UNil  :: UList a
  51.   UCons :: a -> UList a -> UList a
  52.  
  53. instance Semigroup (UList a) where
  54.   (<>) = (++)
  55.  
  56. #if MIN_VERSION_base(4,9,0)
  57. instance Monoid (UList a) where
  58.   mempty = UNil
  59. #if !MIN_VERSION_base(4,11,0)
  60.   mappend = (<>)
  61. #endif
  62. #endif
  63.  
  64. -- | 'map' @f xs@ is the list obtained by applying @f@ to each element
  65. -- of @xs@, i.e.,
  66. --
  67. -- > map f [x1, x2, ..., xn] == [f x1, f x2, ..., f xn]
  68. -- > map f [x1, x2, ...] == [f x1, f x2, ...]
  69. map :: (a -> b) -> UList a -> UList b
  70. {-# NOINLINE [0] map #-}
  71. map _ UNil = UNil
  72. map f (UCons x xs) = UCons (f x) (map f xs)
  73.  
  74. mapFB :: forall (a :: TYPE 'UnliftedRep)
  75.                (elt :: TYPE 'UnliftedRep)
  76.                 (lst :: Type).
  77.      (elt -> lst -> lst) -> (a -> elt) -> a -> lst -> lst
  78. {-# INLINE [0] mapFB #-}
  79. mapFB c f = \x ys -> c (f x) ys
  80.  
  81. build :: forall a. (forall b. (a -> b -> b) -> b -> b) -> UList a
  82. {-# INLINE [1] build #-}
  83. build g = g UCons UNil
  84.  
  85. augment :: forall a. (forall b. (a -> b -> b) -> b -> b) -> UList a -> UList a
  86. {-# INLINE [1] augment #-}
  87. augment g xs = g UCons xs
  88.  
  89. -- | 'foldr', applied to a binary operator, a starting value (typically
  90. -- the right-identity of the operator), and a list, reduces the list
  91. -- using the binary operator, from right to left:
  92. --
  93. -- > foldr f z [x1, x2, ..., xn] == x1 `f` (x2 `f` ... (xn `f` z)...)
  94. foldr :: (a -> b -> b) -> b -> UList a -> b
  95. {-# INLINE [0] foldr #-}
  96. foldr k z = go
  97.   where
  98.     go UNil = z
  99.     go (UCons y ys) = y `k` go ys
  100.  
  101. -- | 'foldl', applied to a binary operator, a starting value (typically
  102. -- the left-identity of the operator), and a list, reduces the list
  103. -- using the binary operator, from left to right:
  104. --
  105. -- > foldl f z [x1, x2, ..., xn] == (...((z `f` x1) `f` x2) `f`...) `f` xn
  106. --
  107. -- The list must be finite.
  108. foldl :: forall a b. (b -> a -> b) -> b -> UList a -> b
  109. {-# INLINE foldl #-}
  110. foldl k z0 xs = foldr
  111.   (\(v :: a) (fn :: b -> b) -> oneShot (\(z :: b) -> fn (k z v)))
  112.   (id :: b -> b)
  113.   xs
  114.   z0
  115.  
  116. -- | A strict version of 'foldl'.
  117. foldl' :: forall a b. (b -> a -> b) -> b -> UList a -> b
  118. {-# INLINE foldl' #-}
  119. foldl' k z0 xs = foldr
  120.  (\(v :: a) (fn :: b -> b) -> oneShot (\(z :: b) -> z `seq` fn (k z v)))
  121.  (id :: b -> b)
  122.  xs
  123.  z0
  124.  
  125. -- | Test whether a list is empty.
  126. null :: UList a -> Bool
  127. null UNil = True
  128. null _    = False
  129.  
  130. -- | 'scanl' is similar to 'foldl', but returns a list of successive
  131. -- reduced values from the left:
  132. --
  133. -- > scanl f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...]
  134. --
  135. -- Note that
  136. --
  137. -- > last (scanl f z xs) == foldl f z xs.
  138.  
  139. -- This peculiar arrangement is necessary to prevent scanl being rewritten in
  140. -- its own right-hand side.
  141. scanl :: (b -> a -> b) -> b -> UList a -> UList b
  142. {-# NOINLINE [1] scanl #-}
  143. scanl = scanlGo
  144.  where
  145.    scanlGo f q ls = UCons q
  146.      (case ls of
  147.        UNil -> UNil
  148.        UCons x xs -> scanlGo f (f q x) xs
  149.      )
  150.  
  151. {-# RULES
  152. "scanl" [~1] forall f a bs. scanl f a bs =
  153.  build (\c n -> a `c` foldr (scanlFB f c) (\_ -> n) bs a)
  154. "scanList" [1] forall f (a::a) bs.
  155.  foldr (scanlFB f UCons) (\_ -> UNil) bs a = tail (scanl f a bs)
  156.  #-}
  157.  
  158. tail :: UList a -> UList a
  159. tail UNil = UNil
  160. tail (UCons _ xs) = xs
  161.  
  162. {-# INLINE [0] scanlFB #-}
  163. scanlFB :: forall (a :: TYPE 'UnliftedRep)
  164.                   (b :: TYPE 'UnliftedRep)
  165.                  (c :: Type).
  166.                  (b -> a -> b) -> (b -> c -> c) -> a -> (b -> c) -> b -> c
  167. scanlFB f c = \b g -> oneShot (\x -> let b' = f x b in b' `c` g b')
  168.  
  169. -- | Append two lists, i.e.,
  170. --
  171. -- > [x1, ..., xm] ++ [y1, ..., yn] == [x1, ..., xm, y1, ..., yn]
  172. -- > [x1, ..., xm] ++ [y1, ...] == [x1, ..., xm, y1, ...]
  173. --
  174. -- If the first list is not finite, the result is the first list.
  175. (++) :: UList a -> UList a -> UList a
  176. {-# NOINLINE [1] (++) #-}
  177. (++) UNil ys = ys
  178. (++) (UCons x xs) ys = UCons x (xs ++ ys)
  179.  
  180. {-# RULES
  181. "++" [~1] forall xs ys. xs ++ ys = augment (\c n -> foldr c n xs) ys
  182.   #-}
  183.  
  184. -- | 'filter', applied to a predicate and a list, returns the list of
  185. -- those elements that satisfy the predicate; i.e.,
  186. --
  187. -- > filter p xs = [ x | x <- xs, p x]
  188. filter :: (a -> Bool) -> UList a -> UList a
  189. {-# NOINLINE [1] filter #-}
  190. filter _ UNil = UNil
  191. filter pred (UCons x xs) = if pred x
  192.   then UCons x (filter pred xs)
  193.   else filter pred xs
  194.  
  195. -- | /O(n)/. 'length' returns the length of a finite list as an 'Int'.
  196. length :: UList a -> Int
  197. {-# NOINLINE [1] length #-}
  198. length xs = lenAcc xs 0
  199.  
  200. lenAcc :: UList a -> Int -> Int
  201. lenAcc UNil n = n
  202. lenAcc (UCons _ ys) n = lenAcc ys (n + 1)
  203.  
  204. {-# RULES
  205. "map" [~1] forall f xs. map f xs = build (\c n -> foldr (mapFB c f) n xs)
  206. "mapList" [1] forall f. foldr (mapFB UCons f) UNil = map f
  207. "mapFB" forall c f g. mapFB (mapFB c f) g = mapFB c (f . g)
  208. "mapFB/id" forall c. mapFB c (\x -> x) = c
  209. #-}
  210.  
  211. -- Coercible (a :: Type) (b :: Type)
  212. -- {-# RULES "map/coerce" [1] map coerce = coerce #-}
  213.  
  214. -- This needs something like `class Eq (a :: TYPE 'UnliftedRep)`
  215. -- elem :: a -> UList a -> Bool
  216. -- elem _ UNil = False
  217. -- elem x (y:ys) = x == y || elem x ys
  218.  
  219. pure, singleton :: a -> UList a
  220. singleton a = UCons a UNil
  221. pure = singleton
  222.  
  223. cons :: a -> UList a -> UList a
  224. cons = UCons
  225.  
  226. traverse_ :: forall f a b. A.Applicative f => (a -> f b) -> UList a -> f ()
  227. traverse_ f = foldr seqd (A.pure ())
  228.   where
  229.   seqd :: a -> f () -> f ()
  230.   seqd a = (A.*>) (f a)
  231.  
  232. -- | The concatenation of all the elements of a container of ULists.
  233. concat :: F.Foldable t => t (UList a) -> (UList a)
  234. concat xs = build (\f a -> F.foldr (\x y -> foldr f y x) a xs)
  235. {-# INLINE concat #-}
  236.  
  237. -- | Map a function over all the elements of a container and concatenate
  238. -- the resulting ULists.
  239. concatMap :: F.Foldable t => (a -> UList b) -> t a -> UList b
  240. concatMap f xs = build (\c n -> F.foldr (\x b -> foldr c b (f x)) n xs)
  241. {-# INLINE concatMap #-}
  242.  
  243. foldMap :: Monoid m => (a -> m) -> UList a -> m
  244. foldMap f = foldr fun mempty
  245.   where
  246.   fun x = mappend (f x)
  247.  
  248. foldlM :: Monad m => (b -> a -> m b) -> b -> UList a -> m b
  249. foldlM f z0 xs = foldr f' return xs z0
  250.  where f' x k z = f z x >>= k
  251.  
  252. -- | Monadic fold over the elements of a structure,
  253. -- associating to the right, i.e. from right to left.
  254. foldrM :: Monad m => (a -> b -> m b) -> b -> UList a -> m b
  255. foldrM f z0 xs = foldl f' return xs z0
  256.  where f' k x z = f x z >>= k
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement