-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathElsewhere.hs
145 lines (114 loc) · 3.76 KB
/
Elsewhere.hs
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
{-# OPTIONS_GHC -Wextra #-}
{-# OPTIONS_GHC -Wno-implicit-prelude -Wno-missing-import-lists -Wno-orphans #-}
{-# OPTIONS_GHC -Wno-unsafe #-}
module Elsewhere
( textZipper, zipperText
, everything
, proxy
, trEv, trDyn, trDynM
, avgStep, average
, goldenRatio
, (.:)
, rcomp
, flip2
, choosePartially
, catchAny
, partial
, showTime
, timeDiff
, printTimeDiff
, (<:)
)
where
import qualified Data.TypeMap.Dynamic as TM
import qualified Data.Text as T
import qualified Data.Text.Zipper as T
import ExternalImports
-- * 'lub' + 'linear'
instance Ord a ⇒ HasLub (V2 a) where lub = liftA2 max
instance Ord a ⇒ HasGlb (V2 a) where glb = liftA2 min
-- * 'base' + 'random'
--
instance Random a ⇒ Random (Complex a) where
randomR (r:+i, r':+i') = runState $ liftA2 (:+) (state $ randomR (r,r')) (state $ randomR (i,i'))
random = runState $ liftA2 (:+) (state $ random) (state $ random)
-- * Text.Zipper
--
textZipper ∷ [T.Text] → T.TextZipper T.Text
textZipper = flip T.textZipper Nothing
zipperText ∷ T.TextZipper T.Text → T.Text
zipperText = T.dropEnd 1 ∘ T.unlines ∘ T.getText
-- * Reflex
--
trEv ∷ Reflex t ⇒ String → Event t a → Event t a
trEv = traceEventWith ∘ const
trDyn ∷ Reflex t ⇒ String → Dynamic t a → Dynamic t a
trDyn = traceDynWith ∘ const
trDynM ∷ Reflex t ⇒ String → String → Dynamic t (Maybe a) → Dynamic t (Maybe a)
trDynM no ju = traceDynWith (\case; Nothing → no; Just _ → ju)
type Avg a = (Int, Int, [a])
avgStep ∷ Fractional a ⇒ a → (a, Avg a) → (a, Avg a)
avgStep x (_, (lim, cur, xs)) =
let (ncur, nxs) = if cur < lim
then (cur + 1, x:xs)
else (lim, x:Prelude.init xs)
in ((sum nxs) / fromIntegral ncur, (lim, ncur, nxs))
average ∷ (Fractional a, Reflex t, MonadHold t m, MonadFix m) ⇒ Int → Event t a → m (Dynamic t a)
average n e = (fst <$>) <$> foldDyn avgStep (0, (n, 0, [])) e
-- * Pretty numbers
--
goldenRatio ∷ Double
goldenRatio = 1.61803398875
-- * Generic functions
--
(.:) ∷ ∀ a f g b. (b → a) → (f → g → b) → f → g → a
(.:) = (.) ∘ (.)
{-# INLINE (.:) #-}
infixr 9 .:
rcomp ∷ (a → b) → (b → c) → (a → c)
rcomp = flip (.)
{-# INLINE rcomp #-}
flip2 ∷ (a → b → c → d) → b → c → a → d
flip2 f b c a = f a b c
{-# INLINE flip2 #-}
choosePartially ∷ Eq a ⇒ a → a → a → a
choosePartially one l r = fromMaybe one $ partial (≢ one) l <|> partial (≢ one) r
everything :: (Enum a, Bounded a) => [a]
everything = enumFromTo minBound maxBound
proxy ∷ a → Proxy a
proxy = const Proxy
{-# INLINE proxy #-}
-- * Exceptions
--
catchAny ∷ IO a → (SomeException → IO a) → IO a
catchAny guarded handler = catch guarded onExc
where onExc e | shouldCatch e = handler e
| otherwise = throwIO e
shouldCatch e
| show e ≡ "<<timeout>>" = False
| Just (_ ∷ AsyncException) ← fromException e = False
| otherwise = True
-- * Simple benchmarking functions from lambdacube-quake3
--
showTime ∷ NominalDiffTime → String
showTime delta
| t > 1e-1 = printf "%.3fs" t
| t > 1e-3 = printf "%.1fms" (t/1e-3)
| otherwise = printf "%.0fus" (t/1e-6)
where
t = realToFrac delta :: Double
timeDiff ∷ IO a → IO (NominalDiffTime, a)
timeDiff m = (\s x e -> (diffUTCTime e s, x))
<$> getCurrentTime
<*> m
<*> getCurrentTime
printTimeDiff ∷ String → IO a → IO a
printTimeDiff message m = do
(t,r) <- timeDiff m
putStr message
putStrLn $ showTime t
return r
-- * In progress
--
(<:) ∷ Typeable b ⇒ TM.TypeMap a → (Proxy b, TM.Item a b) → TM.TypeMap a
(<:) tm (k, v) = TM.insert k v tm