Skip to content

Commit 4de75f0

Browse files
committed
Nix.Utils: clean-up; add Nix.Unused
Moved function got some alteration. Reduced Lazy -> Strict marchalling. Also instead of Lazy used Strict data types, since on the conveyor that data seems to be consumed fully (which I may be wrong about).
1 parent 11ed79b commit 4de75f0

File tree

5 files changed

+152
-123
lines changed

5 files changed

+152
-123
lines changed

hnix.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ library
393393
Nix.XML
394394
other-modules:
395395
Paths_hnix
396+
Nix.Unused
396397
autogen-modules:
397398
Paths_hnix
398399
hs-source-dirs:

src/Nix/Builtins.hs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,23 @@ mkNVBool
164164
-> NValue t f m
165165
mkNVBool = nvConstant . NBool
166166

167+
data NixPathEntryType
168+
= PathEntryPath
169+
| PathEntryURI
170+
deriving (Show, Eq)
171+
172+
-- | @NIX_PATH@ is colon-separated, but can also contain URLs, which have a colon
173+
-- (i.e. @https://...@)
174+
uriAwareSplit :: Text -> [(Text, NixPathEntryType)]
175+
uriAwareSplit txt =
176+
case Text.break (== ':') txt of
177+
(e1, e2)
178+
| Text.null e2 -> [(e1, PathEntryPath)]
179+
| "://" `Text.isPrefixOf` e2 ->
180+
let ((suffix, _) : path) = uriAwareSplit (Text.drop 3 e2) in
181+
(e1 <> "://" <> suffix, PathEntryURI) : path
182+
| otherwise -> (e1, PathEntryPath) : uriAwareSplit (Text.drop 1 e2)
183+
167184
foldNixPath
168185
:: forall e t f m r
169186
. MonadNix e t f m

src/Nix/Json.hs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@ module Nix.Json where
33

44
import qualified Data.Aeson as A
55
import qualified Data.Aeson.Encoding as A
6-
import qualified Data.HashMap.Lazy as HM
7-
import qualified Data.Text.Lazy.Encoding as TL
86
import qualified Data.Vector as V
7+
import qualified Data.HashMap.Strict as HM
98
import Nix.Atoms
109
import Nix.Effects
1110
import Nix.Exec
@@ -15,12 +14,24 @@ import Nix.Value
1514
import Nix.Value.Monad
1615
import Nix.Expr.Types
1716

17+
-- This was moved from Utils.
18+
toEncodingSorted :: A.Value -> A.Encoding
19+
toEncodingSorted = \case
20+
A.Object m ->
21+
A.pairs
22+
. mconcat
23+
. ((\(k, v) -> A.pair k $ toEncodingSorted v) <$>)
24+
. sortWith fst
25+
$ HM.toList m
26+
A.Array l -> A.list toEncodingSorted $ V.toList l
27+
v -> A.toEncoding v
28+
1829
nvalueToJSONNixString :: MonadNix e t f m => NValue t f m -> m NixString
1930
nvalueToJSONNixString =
2031
runWithStringContextT .
2132
fmap
22-
( toStrict
23-
. TL.decodeUtf8
33+
( decodeUtf8
34+
-- This is completely not optimal, but seems we do not have better encoding analog (except for @unsafe*@), Aeson gatekeeps through this.
2435
. A.encodingToLazyByteString
2536
. toEncodingSorted
2637
)

src/Nix/Unused.hs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
{-# language FunctionalDependencies #-}
2+
{-# language TemplateHaskell #-}
3+
4+
{-# options_ghc -Wno-missing-signatures #-}
5+
6+
-- | This module holds unused code.
7+
-- So, if someone wants something - look here, use it & move to appropriate place.
8+
module Nix.Unused
9+
where
10+
11+
import Control.Monad.Free ( Free(..) )
12+
import Data.Fix ( Fix(..) )
13+
import Lens.Family2.TH ( makeLensesBy )
14+
15+
-- * From "Nix.Utils"
16+
17+
-- | > type AlgM f m a = f a -> m a
18+
type AlgM f m a = f a -> m a
19+
20+
whenFree :: (Monoid b)
21+
=> (f (Free f a) -> b) -> Free f a -> b
22+
whenFree =
23+
free
24+
mempty
25+
{-# inline whenFree #-}
26+
27+
whenPure :: (Monoid b)
28+
=> (a -> b) -> Free f a -> b
29+
whenPure f =
30+
free
31+
f
32+
mempty
33+
{-# inline whenPure #-}
34+
35+
-- | Replace:
36+
-- @Pure a -> a@
37+
-- @Free -> Fix@
38+
freeToFix :: Functor f => (a -> Fix f) -> Free f a -> Fix f
39+
freeToFix f = go
40+
where
41+
go =
42+
free
43+
f
44+
$ Fix . (go <$>)
45+
46+
-- | Replace:
47+
-- @a -> Pure a@
48+
-- @Fix -> Free@
49+
fixToFree :: Functor f => Fix f -> Free f a
50+
fixToFree = Free . go
51+
where
52+
go (Fix f) = Free . go <$> f
53+
54+
55+
loeb :: Functor f => f (f a -> a) -> f a
56+
loeb x = go
57+
where
58+
go = ($ go) <$> x
59+
60+
adiM
61+
:: ( Traversable t
62+
, Monad m
63+
)
64+
=> Transform t (m a)
65+
-> AlgM t m a
66+
-> Fix t
67+
-> m a
68+
adiM g f = g $ f <=< traverse (adiM g f) . unFix
69+
70+
para :: Functor f => (f (Fix f, a) -> a) -> Fix f -> a
71+
para f = f . fmap (id &&& para f) . unFix
72+
73+
paraM :: (Traversable f, Monad m) => (f (Fix f, a) -> m a) -> Fix f -> m a
74+
paraM f = f <=< traverse (\x -> (x, ) <$> paraM f x) . unFix
75+
76+
cataP :: Functor f => (Fix f -> f a -> a) -> Fix f -> a
77+
cataP f x = f x . fmap (cataP f) . unFix $ x
78+
79+
cataPM :: (Traversable f, Monad m) => (Fix f -> f a -> m a) -> Fix f -> m a
80+
cataPM f x = f x <=< traverse (cataPM f) . unFix $ x
81+
82+
$(makeLensesBy (\n -> pure $ "_" <> n) ''Fix)

src/Nix/Utils.hs

Lines changed: 37 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,31 @@
11
{-# language NoImplicitPrelude #-}
22
{-# language CPP #-}
3-
{-# language FunctionalDependencies #-}
4-
{-# language TemplateHaskell #-}
53
{-# language GeneralizedNewtypeDeriving #-}
64

7-
{-# options_ghc -Wno-missing-signatures #-}
8-
95
-- | This is a module of custom "Prelude" code.
106
-- It is for import for projects other then @HNix@.
117
-- For @HNix@ - this module gets reexported by "Prelude", so for @HNix@ please fix-up pass-through there.
128
module Nix.Utils
13-
( module Nix.Utils
9+
( KeyMap
10+
, TransformF
11+
, Transform
12+
, Alg
13+
, Path(..)
14+
, Has(..)
15+
, trace
16+
, traceM
17+
, stub
18+
, whenTrue
19+
, list
20+
, whenText
21+
, free
22+
, dup
23+
, mapPair
24+
, both
25+
, readFile
26+
, lifted
27+
, loebM
28+
, adi
1429
, module X
1530
)
1631
where
@@ -30,12 +45,9 @@ import Control.Monad.Fix ( MonadFix(..) )
3045
import Control.Monad.Free ( Free(..) )
3146
import Control.Monad.Trans.Control ( MonadTransControl(..) )
3247
import qualified Data.Aeson as A
33-
import qualified Data.Aeson.Encoding as A
3448
import Data.Fix ( Fix(..) )
35-
import qualified Data.HashMap.Lazy as M
3649
import qualified Data.Text as Text
3750
import qualified Data.Text.IO as Text
38-
import qualified Data.Vector as V
3951
import Lens.Family2 as X
4052
( view
4153
, over
@@ -45,7 +57,6 @@ import Lens.Family2 as X
4557
import Lens.Family2.Stock ( _1
4658
, _2
4759
)
48-
import Lens.Family2.TH ( makeLensesBy )
4960

5061
#if ENABLE_TRACING
5162
import qualified Relude.Debug as X
@@ -59,8 +70,6 @@ traceM = const pass
5970
{-# inline traceM #-}
6071
#endif
6172

62-
$(makeLensesBy (\n -> pure $ "_" <> n) ''Fix)
63-
6473
-- | To have explicit type boundary between FilePath & String.
6574
newtype Path = Path FilePath
6675
deriving
@@ -84,9 +93,6 @@ type KeyMap = HashMap Text
8493
-- > type Alg f a = f a -> a
8594
type Alg f a = f a -> a
8695

87-
-- | > type AlgM f m a = f a -> m a
88-
type AlgM f m a = f a -> m a
89-
9096
-- | Do according transformation.
9197
--
9298
-- It is a transformation of a recursion scheme.
@@ -99,28 +105,25 @@ type Transform f a = TransformF (Fix f) a
99105
-- You got me, it is a natural transformation.
100106
type TransformF f a = (f -> a) -> f -> a
101107

102-
loeb :: Functor f => f (f a -> a) -> f a
103-
loeb x = go
104-
where
105-
go = ($ go) <$> x
108+
class Has a b where
109+
hasLens :: Lens' a b
110+
111+
instance Has a a where
112+
hasLens f = f
113+
114+
instance Has (a, b) a where
115+
hasLens = _1
116+
117+
instance Has (a, b) b where
118+
hasLens = _2
106119

107120
loebM :: (MonadFix m, Traversable t) => t (t a -> m a) -> m (t a)
108121
-- Sectioning here insures optimization happening.
109122
loebM f = mfix $ \a -> (`traverse` f) ($ a)
110123
{-# inline loebM #-}
111124

112-
para :: Functor f => (f (Fix f, a) -> a) -> Fix f -> a
113-
para f = f . fmap (id &&& para f) . unFix
114-
115-
paraM :: (Traversable f, Monad m) => (f (Fix f, a) -> m a) -> Fix f -> m a
116-
paraM f = f <=< traverse (\x -> (x, ) <$> paraM f x) . unFix
117-
118-
cataP :: Functor f => (Fix f -> f a -> a) -> Fix f -> a
119-
cataP f x = f x . fmap (cataP f) . unFix $ x
120-
121-
cataPM :: (Traversable f, Monad m) => (Fix f -> f a -> m a) -> Fix f -> m a
122-
cataPM f x = f x <=< traverse (cataPM f) . unFix $ x
123-
125+
-- 2021-08-21: NOTE: Someone needs to put in normal words, what this does.
126+
-- This function is pretty spefic & used only once, in "Nix.Normal".
124127
lifted
125128
:: (MonadTransControl u, Monad (u m), Monad m)
126129
=> ((a -> m (StT u b)) -> m (StT u b))
@@ -131,29 +134,12 @@ lifted f k =
131134
lftd <- liftWith (\run -> f (run . k))
132135
restoreT $ pure lftd
133136

134-
-- | Replace:
135-
-- @Pure a -> a@
136-
-- @Free -> Fix@
137-
freeToFix :: Functor f => (a -> Fix f) -> Free f a -> Fix f
138-
freeToFix f = go
139-
where
140-
go =
141-
free
142-
f
143-
$ Fix . (go <$>)
144-
145-
-- | Replace:
146-
-- @a -> Pure a@
147-
-- @Fix -> Free@
148-
fixToFree :: Functor f => Fix f -> Free f a
149-
fixToFree = Free . go
150-
where
151-
go (Fix f) = Free . go <$> f
152-
153137
-- | adi is Abstracting Definitional Interpreters:
154138
--
155139
-- https://arxiv.org/abs/1707.04755
156140
--
141+
-- All ADI does is interleaves every layer of evaluation by inserting intermitten layers between them, in that way the evaluation can be extended/embelished in any way wanted. Look at its use to see great examples.
142+
--
157143
-- Essentially, it does for evaluation what recursion schemes do for
158144
-- representation: allows threading layers through existing structure, only
159145
-- in this case through behavior.
@@ -165,53 +151,6 @@ adi
165151
-> a
166152
adi g f = g $ f . (adi g f <$>) . unFix
167153

168-
adiM
169-
:: ( Traversable t
170-
, Monad m
171-
)
172-
=> Transform t (m a)
173-
-> AlgM t m a
174-
-> Fix t
175-
-> m a
176-
adiM g f = g $ f <=< traverse (adiM g f) . unFix
177-
178-
179-
class Has a b where
180-
hasLens :: Lens' a b
181-
182-
instance Has a a where
183-
hasLens f = f
184-
185-
instance Has (a, b) a where
186-
hasLens = _1
187-
188-
instance Has (a, b) b where
189-
hasLens = _2
190-
191-
toEncodingSorted :: A.Value -> A.Encoding
192-
toEncodingSorted = \case
193-
A.Object m ->
194-
A.pairs
195-
. mconcat
196-
. ((\(k, v) -> A.pair k $ toEncodingSorted v) <$>)
197-
. sortWith fst
198-
$ M.toList m
199-
A.Array l -> A.list toEncodingSorted $ V.toList l
200-
v -> A.toEncoding v
201-
202-
data NixPathEntryType = PathEntryPath | PathEntryURI deriving (Show, Eq)
203-
204-
-- | @NIX_PATH@ is colon-separated, but can also contain URLs, which have a colon
205-
-- (i.e. @https://...@)
206-
uriAwareSplit :: Text -> [(Text, NixPathEntryType)]
207-
uriAwareSplit txt =
208-
case Text.break (== ':') txt of
209-
(e1, e2)
210-
| Text.null e2 -> [(e1, PathEntryPath)]
211-
| "://" `Text.isPrefixOf` e2 ->
212-
let ((suffix, _) : path) = uriAwareSplit (Text.drop 3 e2) in
213-
(e1 <> "://" <> suffix, PathEntryURI) : path
214-
| otherwise -> (e1, PathEntryPath) : uriAwareSplit (Text.drop 1 e2)
215154

216155
-- | Analog for @bool@ or @maybe@, for list-like cons structures.
217156
list
@@ -248,29 +187,6 @@ whenTrue =
248187
mempty
249188
{-# inline whenTrue #-}
250189

251-
whenFalse :: (Monoid a)
252-
=> a -> Bool -> a
253-
whenFalse f =
254-
bool
255-
f
256-
mempty
257-
{-# inline whenFalse #-}
258-
259-
whenFree :: (Monoid b)
260-
=> (f (Free f a) -> b) -> Free f a -> b
261-
whenFree =
262-
free
263-
mempty
264-
{-# inline whenFree #-}
265-
266-
whenPure :: (Monoid b)
267-
=> (a -> b) -> Free f a -> b
268-
whenPure f =
269-
free
270-
f
271-
mempty
272-
{-# inline whenPure #-}
273-
274190

275191
-- | Apply a single function to both components of a pair.
276192
--
@@ -300,3 +216,5 @@ stub = pure mempty
300216

301217
readFile :: Path -> IO Text
302218
readFile = Text.readFile . coerce
219+
220+

0 commit comments

Comments
 (0)