File: Prelude.hs

package info (click to toggle)
haskell-lambdahack 0.11.0.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,064 kB
  • sloc: haskell: 45,636; makefile: 223
file content (223 lines) | stat: -rw-r--r-- 6,814 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -Wno-orphans #-}
-- | Custom Prelude, compatible across many GHC versions.
module Game.LambdaHack.Core.Prelude
  ( module Prelude.Compat

  , module Control.Monad.Compat
  , module Data.List.Compat
  , module Data.Maybe
  , module Data.Semigroup.Compat

  , module Control.Exception.Assert.Sugar

  , Text, (<+>), tshow, divUp, sum, (<$$>), partitionM, length, null, comparing
  , into, fromIntegralWrap, toIntegralCrash, intToDouble, int64ToDouble
  , mapM_, forM_, vectorUnboxedUnsafeIndex, unsafeShiftL, unsafeShiftR

  , (***), (&&&), first, second
  ) where

import Prelude ()

import Prelude.Compat hiding
  ( appendFile
  , foldl
  , foldl1
  , fromIntegral
  , length
  , mapM_
  , null
  , readFile
  , sum
  , (<>)
  )

import           Control.Applicative
import           Control.Arrow (first, second, (&&&), (***))
import           Control.DeepSeq
import           Control.Exception.Assert.Sugar
  (allB, assert, blame, showFailure, swith)
import           Control.Monad.Compat hiding (forM_, mapM_)
import qualified Control.Monad.Compat
import           Data.Binary
import qualified Data.Bits as Bits
import qualified Data.EnumMap.Strict as EM
import qualified Data.EnumSet as ES
import qualified Data.Fixed as Fixed
import qualified Data.HashMap.Strict as HM
import           Data.Hashable
import           Data.Int (Int64)
import           Data.Key
import           Data.List.Compat hiding (foldl, foldl1, length, null, sum)
import qualified Data.List.Compat as List
import           Data.Maybe
import           Data.Ord (comparing)
import           Data.Semigroup.Compat (Semigroup ((<>)))
import           Data.Text (Text)
import qualified Data.Text as T (pack)
import qualified Data.Time as Time
import qualified Data.Vector.Unboxed as U
import           NLP.Miniutter.English ((<+>))
import qualified NLP.Miniutter.English as MU
import qualified Prelude.Compat
import           Witch (into)

-- | Show and pack the result.
tshow :: Show a => a -> Text
tshow x = T.pack $ show x

infixl 7 `divUp`
-- | Integer division, rounding up.
divUp :: Integral a => a -> a -> a
{-# INLINE divUp #-}
divUp n k = (n + k - 1) `div` k

sum :: Num a => [a] -> a
sum = foldl' (+) 0

infixl 4 <$$>
(<$$>) :: (Functor f, Functor g) => (a -> b) -> f (g a) -> f (g b)
h <$$> m = fmap h <$> m

partitionM :: Applicative m => (a -> m Bool) -> [a] -> m ([a], [a])
{-# INLINE partitionM #-}
partitionM p = foldr (\a ->
  liftA2 (\b -> (if b then first else second) (a :)) (p a)) (pure ([], []))

-- | A version specialized to lists to avoid errors such as taking length
-- of @Maybe [a]@ instead of @[a]@.
-- Such errors are hard to detect, because the type of elements of the list
-- is not constrained.
length :: [a] -> Int
length = List.length

-- | A version specialized to lists to avoid errors such as taking null
-- of @Maybe [a]@ instead of @[a]@.
-- Such errors are hard to detect, because the type of elements of the list
-- is not constrained.
null :: [a] -> Bool
null = List.null

-- Data.Binary orphan instances

instance (Enum k, Binary k, Binary e) => Binary (EM.EnumMap k e) where
  put m = put (EM.size m) >> mapM_ put (EM.toAscList m)
  get = EM.fromDistinctAscList <$> get

instance (Enum k, Binary k) => Binary (ES.EnumSet k) where
  put m = put (ES.size m) >> mapM_ put (ES.toAscList m)
  get = ES.fromDistinctAscList <$> get

instance Binary Time.NominalDiffTime where
  get = fmap realToFrac (get :: Get Fixed.Pico)
  put = (put :: Fixed.Pico -> Put) . realToFrac

instance (Hashable k, Eq k, Binary k, Binary v) => Binary (HM.HashMap k v) where
  get = fmap HM.fromList get
  put = put . HM.toList

-- Data.Key orphan instances

type instance Key (EM.EnumMap k) = k

instance Zip (EM.EnumMap k) where
  {-# INLINE zipWith #-}
  zipWith = EM.intersectionWith

instance Enum k => ZipWithKey (EM.EnumMap k) where
  {-# INLINE zipWithKey #-}
  zipWithKey = EM.intersectionWithKey

instance Enum k => Keyed (EM.EnumMap k) where
  {-# INLINE mapWithKey #-}
  mapWithKey = EM.mapWithKey

instance Enum k => FoldableWithKey (EM.EnumMap k) where
  {-# INLINE foldrWithKey #-}
  foldrWithKey = EM.foldrWithKey

instance Enum k => TraversableWithKey (EM.EnumMap k) where
  traverseWithKey f = fmap EM.fromDistinctAscList
                      . traverse (\(k, v) -> (,) k <$> f k v) . EM.toAscList

instance Enum k => Indexable (EM.EnumMap k) where
  {-# INLINE index #-}
  index = (EM.!)

instance Enum k => Lookup (EM.EnumMap k) where
  {-# INLINE lookup #-}
  lookup = EM.lookup

instance Enum k => Adjustable (EM.EnumMap k) where
  {-# INLINE adjust #-}
  adjust = EM.adjust

-- Data.Hashable orphan instances

instance (Enum k, Hashable k, Hashable e) => Hashable (EM.EnumMap k e) where
  hashWithSalt s x = hashWithSalt s (EM.toAscList x)

instance (Enum k, Hashable k) => Hashable (ES.EnumSet k) where
  hashWithSalt s x = hashWithSalt s (ES.toAscList x)

-- Control.DeepSeq orphan instances

instance NFData MU.Part

instance NFData MU.Person

instance NFData MU.Polarity

-- | Re-exported 'Prelude.fromIntegral', but please give it explicit type
-- to make it obvious if wrapping, etc., may occur. Use `toIntegralCrash`
-- instead, if possible, because it fails instead of wrapping, etc.
-- In general, it may wrap or otherwise lose information.
fromIntegralWrap :: (Integral a, Num b) => a -> b
fromIntegralWrap = Prelude.Compat.fromIntegral

-- | Re-exported 'Data.Bits.toIntegralSized', but please give it explicit type
-- to make it obvious if wrapping, etc., may occur and to trigger optimization.
-- In general, it may crash.
toIntegralCrash :: (Integral a, Integral b, Bits.Bits a, Bits.Bits b)
                => a -> b
{-# INLINE toIntegralCrash #-}
toIntegralCrash = fromMaybe (error "toIntegralCrash") . Bits.toIntegralSized

intToDouble :: Int -> Double
intToDouble = Prelude.Compat.fromIntegral

int64ToDouble :: Int64 -> Double
int64ToDouble = Prelude.Compat.fromIntegral

-- | This has a more specific type (unit result) than normally, to catch errors.
mapM_ :: (Foldable t, Monad m) => (a -> m ()) -> t a -> m ()
mapM_ = Control.Monad.Compat.mapM_

-- | This has a more specific type (unit result) than normally, to catch errors.
forM_ :: (Foldable t, Monad m) => t a -> (a -> m ()) -> m ()
forM_ = Control.Monad.Compat.forM_

vectorUnboxedUnsafeIndex :: U.Unbox a => U.Vector a -> Int -> a
vectorUnboxedUnsafeIndex =
#ifdef WITH_EXPENSIVE_ASSERTIONS
  (U.!)  -- index checking is sometimes an expensive (kind of) assertion
#else
  U.unsafeIndex
#endif

unsafeShiftL :: Bits.Bits a => a -> Int -> a
unsafeShiftL =
#ifdef WITH_EXPENSIVE_ASSERTIONS
  Bits.shiftL
#else
  Bits.unsafeShiftL
#endif

unsafeShiftR :: Bits.Bits a => a -> Int -> a
unsafeShiftR =
#ifdef WITH_EXPENSIVE_ASSERTIONS
  Bits.shiftR
#else
  Bits.unsafeShiftR
#endif