From 1c8bad4f6068bc719cf5e5166473b974e218f7fd Mon Sep 17 00:00:00 2001 From: soulomoon Date: Sat, 22 Jan 2022 00:12:36 +0000 Subject: [PATCH 01/12] unify builder and pattern for Value.hs --- src/Nix.hs | 2 +- src/Nix/Builtins.hs | 140 +++++++++++++-------------- src/Nix/Convert.hs | 34 +++---- src/Nix/Effects/Derivation.hs | 6 +- src/Nix/Exec.hs | 26 ++--- src/Nix/Normal.hs | 6 +- src/Nix/Value.hs | 176 ++++++++-------------------------- src/Nix/Value/Equal.hs | 4 +- 8 files changed, 150 insertions(+), 244 deletions(-) diff --git a/src/Nix.hs b/src/Nix.hs index 176b97906..a6cacaf46 100644 --- a/src/Nix.hs +++ b/src/Nix.hs @@ -114,7 +114,7 @@ evaluateExpression mpath evaluator handler expr = f' <- demand f val <- case f' of - NVClosure _ g -> g $ mkNVSet mempty $ M.fromList args + NVClosure _ g -> g $ NVSet mempty $ M.fromList args _ -> pure f processResult handler val where diff --git a/src/Nix/Builtins.hs b/src/Nix/Builtins.hs index 39e6366a3..37376e14e 100644 --- a/src/Nix/Builtins.hs +++ b/src/Nix/Builtins.hs @@ -1,12 +1,13 @@ +{-# LANGUAGE GADTs #-} {-# language CPP #-} {-# language AllowAmbiguousTypes #-} {-# language ConstraintKinds #-} {-# language FunctionalDependencies #-} {-# language KindSignatures #-} -{-# language MonoLocalBinds #-} {-# language MultiWayIf #-} {-# language PartialTypeSignatures #-} {-# language QuasiQuotes #-} +{-# language PatternSynonyms #-} {-# language TemplateHaskell #-} {-# language UndecidableInstances #-} {-# language PackageImports #-} -- 2021-07-05: Due to hashing Haskell IT system situation, in HNix we currently ended-up with 2 hash package dependencies @{hashing, cryptonite}@ @@ -23,7 +24,6 @@ where import Nix.Prelude import GHC.Exception ( ErrorCall(ErrorCall) ) -import Control.Comonad ( Comonad ) import Control.Monad ( foldM ) import Control.Monad.Catch ( MonadCatch(catch) ) import Control.Monad.ListM ( sortByM ) @@ -33,10 +33,10 @@ import qualified "hashing" Crypto.Hash.SHA1 as SHA1 import qualified "hashing" Crypto.Hash.SHA256 as SHA256 import qualified "hashing" Crypto.Hash.SHA512 as SHA512 import qualified Data.Aeson as A -#if MIN_VERSION_aeson(2,0,0) -import qualified Data.Aeson.Key as AKM -import qualified Data.Aeson.KeyMap as AKM -#endif + + + + import Data.Align ( alignWith ) import Data.Array import Data.Bits @@ -126,14 +126,15 @@ instance ) => ToBuiltin t f m (a -> b) where toBuiltin name f = - pure $ mkNVBuiltin (coerce name) $ toBuiltin name . f <=< fromValue . Deeper + pure $ NVBuiltin (coerce name) $ toBuiltin name . f <=< fromValue . Deeper -- *** @WValue@ closure wrapper to have @Ord@ -- We wrap values solely to provide an Ord instance for genericClosure -newtype WValue t f m = WValue (NValue t f m) +data WValue t f m where + WValue :: NvConstraint f => NValue t f m -> WValue t f m -instance Comonad f => Eq (WValue t f m) where +instance Eq (WValue t f m) where WValue (NVConstant (NFloat x)) == WValue (NVConstant (NInt y)) = x == fromInteger y WValue (NVConstant (NInt x)) == WValue (NVConstant (NFloat y)) = @@ -145,7 +146,7 @@ instance Comonad f => Eq (WValue t f m) where ignoreContext x == ignoreContext y _ == _ = False -instance Comonad f => Ord (WValue t f m) where +instance Ord (WValue t f m) where WValue (NVConstant (NFloat x)) <= WValue (NVConstant (NInt y)) = x <= fromInteger y WValue (NVConstant (NInt x)) <= WValue (NVConstant (NFloat y)) = @@ -159,11 +160,8 @@ instance Comonad f => Ord (WValue t f m) where -- ** Helpers -mkNVBool - :: MonadNix e t f m - => Bool - -> NValue t f m -mkNVBool = mkNVConstant . NBool +pattern NVBool :: MonadNix e t f m => Bool -> NValue t f m +pattern NVBool a = NVConstant (NBool a) data NixPathEntryType = PathEntryPath @@ -331,15 +329,15 @@ splitMatches numDropped (((_, (start, len)) : captures) : mts) haystack = relStart = max 0 start - numDropped (before, rest) = B.splitAt relStart haystack caps :: NValue t f m - caps = mkNVList (f <$> captures) + caps = NVList (f <$> captures) f :: (ByteString, (Int, b)) -> NValue t f m f (a, (s, _)) = bool - nvNull + NVNull (thunkStr a) (s >= 0) -thunkStr :: Applicative f => ByteString -> NValue t f m +thunkStr :: NvConstraint f => ByteString -> NValue t f m thunkStr s = mkNVStrWithoutContext $ decodeUtf8 s hasKind @@ -422,16 +420,16 @@ derivationNix = foldFix Eval.eval $$(do nixPathNix :: forall e t f m . MonadNix e t f m => m (NValue t f m) nixPathNix = fmap - mkNVList + NVList $ foldNixPath mempty $ \p mn ty rest -> pure $ pure - (mkNVSet + (NVSet mempty (M.fromList [case ty of - PathEntryPath -> ("path", mkNVPath p) + PathEntryPath -> ("path", NVPath p) PathEntryURI -> ( "uri", mkNVStrWithoutContext $ fromString $ coerce p) , ( "prefix", mkNVStrWithoutContext $ maybeToMonoid mn) @@ -500,7 +498,7 @@ unsafeGetAttrPosNix nvX nvY = case (x, y) of (NVStr ns, NVSet apos _) -> maybe - (pure nvNull) + (pure NVNull) toValue (M.lookup @VarName (coerce $ ignoreContext ns) apos) _xy -> throwError $ ErrorCall $ "Invalid types for builtins.unsafeGetAttrPosNix: " <> show _xy @@ -613,7 +611,7 @@ tailNix :: forall e t f m. MonadNix e t f m => NValue t f m -> m (NValue t f m) tailNix = maybe (throwError $ ErrorCall "builtins.tail: empty list") - (pure . mkNVList) + (pure . NVList) . viaNonEmpty tail <=< fromValue @[NValue t f m] splitVersionNix :: MonadNix e t f m => NValue t f m -> m (NValue t f m) @@ -621,7 +619,7 @@ splitVersionNix v = do version <- fromStringNoContext =<< fromValue v pure $ - mkNVList $ + NVList $ mkNVStrWithoutContext . show <$> splitVersion version @@ -642,7 +640,7 @@ compareVersionsNix t1 t2 = EQ -> 0 GT -> 1 - pure $ mkNVConstant $ NInt cmpVers + pure $ NVConstant $ NInt cmpVers where mkText = fromStringNoContext <=< fromValue @@ -689,7 +687,7 @@ matchNix pat str = re = makeRegex p :: Regex mkMatch t = bool - (pure nvNull) + (pure NVNull) (toValue $ mkNixStringWithoutContext t) (not $ Text.null t) @@ -697,7 +695,7 @@ matchNix pat str = Just ("", sarr, "") -> do let submatches = fst <$> elems sarr - mkNVList <$> + NVList <$> traverse mkMatch (case submatches of @@ -705,7 +703,7 @@ matchNix pat str = [a] -> one a _:xs -> xs -- return only the matched groups, drop the full string ) - _ -> pure nvNull + _ -> pure NVNull splitNix :: forall e t f m @@ -726,7 +724,7 @@ splitNix pat str = regex = makeRegex p :: Regex haystack = encodeUtf8 s - pure $ mkNVList $ splitMatches 0 (elems <$> matchAllText regex haystack) haystack + pure $ NVList $ splitMatches 0 (elems <$> matchAllText regex haystack) haystack substringNix :: forall e t f m. MonadNix e t f m => Int -> Int -> NixString -> Prim m NixString substringNix start len str = @@ -825,7 +823,7 @@ catAttrsNix attrName xs = n <- fromStringNoContext =<< fromValue attrName l <- fromValue @[NValue t f m] xs - mkNVList . catMaybes <$> + NVList . catMaybes <$> traverse (fmap (M.lookup @VarName $ coerce n) . fromValue <=< demand) l @@ -835,7 +833,7 @@ baseNameOfNix x = do ns <- coerceStringlikeToNixString DontCopyToStore x pure $ - mkNVStr $ + NVStr $ modifyNixContents (fromString . coerce takeFileName . toString) ns @@ -927,8 +925,8 @@ dirOfNix nvdir = dir <- demand nvdir case dir of - NVStr ns -> pure $ mkNVStr $ modifyNixContents (fromString . coerce takeDirectory . toString) ns - NVPath path -> pure $ mkNVPath $ takeDirectory path + NVStr ns -> pure $ NVStr $ modifyNixContents (fromString . coerce takeDirectory . toString) ns + NVPath path -> pure $ NVPath $ takeDirectory path v -> throwError $ ErrorCall $ "dirOf: expected string or path, got " <> show v -- jww (2018-04-28): This should only be a string argument, and not coerced? @@ -1158,7 +1156,7 @@ intersectAttrsNix set1 set2 = (s1, p1) <- fromValue @(AttrSet (NValue t f m), PositionSet) set1 (s2, p2) <- fromValue @(AttrSet (NValue t f m), PositionSet) set2 - pure $ mkNVSet (p2 `M.intersection` p1) (s2 `M.intersection` s1) + pure $ NVSet (p2 `M.intersection` p1) (s2 `M.intersection` s1) functionArgsNix :: forall e t f m . MonadNix e t f m => NValue t f m -> m (NValue t f m) @@ -1167,7 +1165,7 @@ functionArgsNix nvfun = fun <- demand nvfun case fun of NVClosure p _ -> - toValue @(AttrSet (NValue t f m)) $ mkNVBool <$> + toValue @(AttrSet (NValue t f m)) $ NVBool <$> case p of Param name -> one (name, False) ParamSet _ _ pset -> isJust <$> M.fromList pset @@ -1272,7 +1270,7 @@ throwNix = -- importNix :: forall e t f m . MonadNix e t f m => NValue t f m -> m (NValue t f m) -importNix = scopedImportNix $ mkNVSet mempty mempty +importNix = scopedImportNix $ NVSet mempty mempty -- | @scopedImport scope path@ -- An undocumented secret powerful function. @@ -1383,7 +1381,7 @@ lessThanNix ta tb = let badType = throwError $ ErrorCall $ "builtins.lessThan: expected two numbers or two strings, got '" <> show va <> "' and '" <> show vb <> "'." - mkNVBool <$> + NVBool <$> case (va, vb) of (NVConstant ca, NVConstant cb) -> case (ca, cb) of @@ -1433,7 +1431,7 @@ listToAttrsNix lst = do l <- fromValue @[NValue t f m] lst fmap - (mkNVSet mempty . M.fromList . reverse) + (NVSet mempty . M.fromList . reverse) (traverse (\ nvattrset -> do @@ -1500,8 +1498,8 @@ groupByNix nvfun nvlist = do list <- demand nvlist fun <- demand nvfun (f, l) <- extractP (fun, list) - mkNVSet mempty - . fmap (mkNVList . reverse) + NVSet mempty + . fmap (NVList . reverse) . M.fromListWith (<>) <$> traverse (app f) l where @@ -1532,14 +1530,14 @@ placeHolderNix p = $ Base32.encode -- Please, stop Text -> Bytestring here after migration to Text $ case Base16.decode (bytes h) of -- The result coming out of hashString is base16 encoded -#if MIN_VERSION_base16_bytestring(1,0,0) + -- Please, stop Text -> String here after migration to Text Left e -> error $ "Couldn't Base16 decode the text: '" <> body h <> "'.\nThe Left fail content: '" <> show e <> "'." Right d -> d -#else - (d, "") -> d - (_, e) -> error $ "Couldn't Base16 decode the text: '" <> body h <> "'.\nUndecodable remainder: '" <> show e <> "'." -#endif + + + + where bytes :: NixString -> ByteString bytes = encodeUtf8 . body @@ -1565,7 +1563,7 @@ findFileNix nvaset nvfilepath = do mres <- findPath @t @f @m x $ coerce $ toString $ ignoreContext ns - pure $ mkNVPath mres + pure $ NVPath mres (NVList _, _y ) -> throwError $ ErrorCall $ "expected a string, got " <> show _y (_x , NVStr _) -> throwError $ ErrorCall $ "expected a list, got " <> show _x @@ -1620,32 +1618,32 @@ fromJSONNix nvjson = \case A.Object m -> traverseToNValue - (mkNVSet mempty) -#if MIN_VERSION_aeson(2,0,0) - (M.mapKeys (coerce . AKM.toText) $ AKM.toHashMap m) -#else + (NVSet mempty) + + + (M.mapKeys coerce m) -#endif - A.Array l -> traverseToNValue mkNVList (V.toList l) + + A.Array l -> traverseToNValue NVList (V.toList l) A.String s -> pure $ mkNVStrWithoutContext s A.Number n -> pure $ - mkNVConstant $ + NVConstant $ either NFloat NInt (floatingOrInteger n) - A.Bool b -> pure $ mkNVBool b - A.Null -> pure nvNull + A.Bool b -> pure $ NVBool b + A.Null -> pure NVNull where traverseToNValue :: Traversable t0 => (t0 (NValue t f m) -> b) -> t0 A.Value -> m b traverseToNValue f v = f <$> traverse jsonToNValue v toJSONNix :: MonadNix e t f m => NValue t f m -> m (NValue t f m) -toJSONNix = (fmap mkNVStr . toJSONNixString) <=< demand +toJSONNix = (fmap NVStr . toJSONNixString) <=< demand toXMLNix :: MonadNix e t f m => NValue t f m -> m (NValue t f m) -toXMLNix = (fmap (mkNVStr . toXML) . normalForm) <=< demand +toXMLNix = (fmap (NVStr . toXML) . normalForm) <=< demand typeOfNix :: MonadNix e t f m => NValue t f m -> m (NValue t f m) typeOfNix nvv = @@ -1677,19 +1675,19 @@ tryEvalNix e = (`catch` (pure . onError)) (onSuccess <$> demand e) where onSuccess v = - mkNVSet + NVSet mempty $ M.fromList - [ ("success", mkNVBool True) + [ ("success", NVBool True) , ("value" , v ) ] onError :: SomeException -> NValue t f m onError _ = - mkNVSet + NVSet mempty $ M.fromList - $ (, mkNVBool False) <$> + $ (, NVBool False) <$> [ "success" , "value" ] @@ -1766,7 +1764,7 @@ partitionNix f nvlst = let (right, wrong) = partition fst selection - makeSide = mkNVList . fmap snd + makeSide = NVList . fmap snd toValue @(AttrSet (NValue t f m)) $ M.fromList @@ -1791,15 +1789,15 @@ currentTimeNix = derivationStrictNix :: MonadNix e t f m => NValue t f m -> m (NValue t f m) derivationStrictNix = derivationStrict -getRecursiveSizeNix :: (MonadIntrospect m, Applicative f) => a -> m (NValue t f m) -getRecursiveSizeNix = fmap (mkNVConstant . NInt . fromIntegral) . recursiveSize +getRecursiveSizeNix :: (MonadIntrospect m, NvConstraint f) => a -> m (NValue t f m) +getRecursiveSizeNix = fmap (NVConstant . NInt . fromIntegral) . recursiveSize getContextNix :: forall e t f m . MonadNix e t f m => NValue t f m -> m (NValue t f m) getContextNix = \case (NVStr ns) -> - mkNVSet mempty <$> traverseToValue (getNixLikeContext $ toNixLikeContext $ getStringContext ns) + NVSet mempty <$> traverseToValue (getNixLikeContext $ toNixLikeContext $ getStringContext ns) x -> throwError $ ErrorCall $ "Invalid type for builtins.getContext: " <> show x <=< demand @@ -1927,7 +1925,7 @@ builtinsList = , add2 Normal "elem" elemNix , add2 Normal "elemAt" elemAtNix , add Normal "exec" execNix - , add0 Normal "false" (pure $ mkNVBool False) + , add0 Normal "false" (pure $ NVBool False) --, add Normal "fetchGit" fetchGit --, add Normal "fetchMercurial" fetchMercurial , add Normal "fetchTarball" fetchTarball @@ -1966,7 +1964,7 @@ builtinsList = , add2 Normal "match" matchNix , add2 Normal "mul" mulNix , add0 Normal "nixPath" nixPathNix - , add0 Normal "null" (pure nvNull) + , add0 Normal "null" (pure NVNull) , add Normal "parseDrvName" parseDrvNameNix , add2 Normal "partition" partitionNix , add Normal "path" pathNix @@ -1988,7 +1986,7 @@ builtinsList = , add Normal "toJSON" toJSONNix , add Normal "toPath" toPathNix -- Deprecated in Nix: https://github.com/NixOS/nix/pull/2524 , add Normal "toXML" toXMLNix - , add0 Normal "true" (pure $ mkNVBool True) + , add0 Normal "true" (pure $ NVBool True) , add Normal "tryEval" tryEvalNix , add Normal "typeOf" typeOfNix , add Normal "unsafeDiscardOutputDependency" unsafeDiscardOutputDependencyNix @@ -2088,7 +2086,7 @@ withNixContext mpath action = opts <- askOptions pushScope - (one ("__includes", mkNVList $ mkNVStrWithoutContext . fromString . coerce <$> getInclude opts)) + (one ("__includes", NVList $ mkNVStrWithoutContext . fromString . coerce <$> getInclude opts)) (pushScopes base $ maybe @@ -2096,7 +2094,7 @@ withNixContext mpath action = (\ path act -> do traceM $ "Setting __cur_file = " <> show path - pushScope (one ("__cur_file", mkNVPath path)) act + pushScope (one ("__cur_file", NVPath path)) act ) mpath action @@ -2110,7 +2108,7 @@ builtins => m (Scopes m (NValue t f m)) builtins = do - ref <- defer $ mkNVSet mempty <$> buildMap + ref <- defer $ NVSet mempty <$> buildMap (`pushScope` askScopes) . coerce . M.fromList . (one ("builtins", ref) <>) =<< topLevelBuiltins where buildMap :: m (HashMap VarName (NValue t f m)) diff --git a/src/Nix/Convert.hs b/src/Nix/Convert.hs index 41bb7ee12..62d7898bf 100644 --- a/src/Nix/Convert.hs +++ b/src/Nix/Convert.hs @@ -370,39 +370,39 @@ instance ( Convertible e t f m instance Convertible e t f m => ToValue () m (NValue' t f m (NValue t f m)) where - toValue = const $ pure nvNull' + toValue = const $ pure NVNull' instance Convertible e t f m => ToValue Bool m (NValue' t f m (NValue t f m)) where - toValue = pure . mkNVConstant' . NBool + toValue = pure . NVConstant' . NBool instance Convertible e t f m => ToValue Int m (NValue' t f m (NValue t f m)) where - toValue = pure . mkNVConstant' . NInt . toInteger + toValue = pure . NVConstant' . NInt . toInteger instance Convertible e t f m => ToValue Integer m (NValue' t f m (NValue t f m)) where - toValue = pure . mkNVConstant' . NInt + toValue = pure . NVConstant' . NInt instance Convertible e t f m => ToValue Float m (NValue' t f m (NValue t f m)) where - toValue = pure . mkNVConstant' . NFloat + toValue = pure . NVConstant' . NFloat instance Convertible e t f m => ToValue NixString m (NValue' t f m (NValue t f m)) where - toValue = pure . mkNVStr' + toValue = pure . NVStr' instance Convertible e t f m => ToValue ByteString m (NValue' t f m (NValue t f m)) where - toValue = pure . mkNVStr' . mkNixStringWithoutContext . decodeUtf8 + toValue = pure . NVStr' . mkNixStringWithoutContext . decodeUtf8 instance Convertible e t f m => ToValue Text m (NValue' t f m (NValue t f m)) where - toValue = pure . mkNVStr' . mkNixStringWithoutContext + toValue = pure . NVStr' . mkNixStringWithoutContext instance Convertible e t f m => ToValue Path m (NValue' t f m (NValue t f m)) where - toValue = pure . mkNVPath' . coerce + toValue = pure . NVPath' . coerce instance Convertible e t f m => ToValue StorePath m (NValue' t f m (NValue t f m)) where @@ -415,40 +415,40 @@ instance Convertible e t f m l' <- toValue $ unPos $ coerce l c' <- toValue $ unPos $ coerce c let pos = M.fromList [("file" :: VarName, f'), ("line", l'), ("column", c')] - pure $ mkNVSet' mempty pos + pure $ NVSet' mempty pos -- | With 'ToValue', we can always act recursively instance Convertible e t f m => ToValue [NValue t f m] m (NValue' t f m (NValue t f m)) where - toValue = pure . mkNVList' + toValue = pure . NVList' instance (Convertible e t f m , ToValue a m (NValue t f m) ) => ToValue [a] m (Deeper (NValue' t f m (NValue t f m))) where - toValue l = Deeper . mkNVList' <$> traverseToValue l + toValue l = Deeper . NVList' <$> traverseToValue l instance Convertible e t f m => ToValue (AttrSet (NValue t f m)) m (NValue' t f m (NValue t f m)) where - toValue s = pure $ mkNVSet' mempty s + toValue s = pure $ NVSet' mempty s instance (Convertible e t f m, ToValue a m (NValue t f m)) => ToValue (AttrSet a) m (Deeper (NValue' t f m (NValue t f m))) where toValue s = - liftA2 (\ v s -> Deeper $ mkNVSet' s v) + liftA2 (\ v s -> Deeper $ NVSet' s v) (traverseToValue s) stub instance Convertible e t f m => ToValue (AttrSet (NValue t f m), PositionSet) m (NValue' t f m (NValue t f m)) where - toValue (s, p) = pure $ mkNVSet' p s + toValue (s, p) = pure $ NVSet' p s instance (Convertible e t f m, ToValue a m (NValue t f m)) => ToValue (AttrSet a, PositionSet) m (Deeper (NValue' t f m (NValue t f m))) where toValue (s, p) = - liftA2 (\ v s -> Deeper $ mkNVSet' s v) + liftA2 (\ v s -> Deeper $ NVSet' s v) (traverseToValue s) (pure p) @@ -472,7 +472,7 @@ instance Convertible e t f m (pure Nothing) (fmap pure . toValue) ts - pure $ mkNVSet' mempty $ M.fromList $ catMaybes + pure $ NVSet' mempty $ M.fromList $ catMaybes [ ("path" ,) <$> path , ("allOutputs",) <$> allOutputs , ("outputs" ,) <$> outputs diff --git a/src/Nix/Effects/Derivation.hs b/src/Nix/Effects/Derivation.hs index fe0989024..27438011d 100644 --- a/src/Nix/Effects/Derivation.hs +++ b/src/Nix/Effects/Derivation.hs @@ -292,10 +292,10 @@ defaultDerivationStrict val = do (\out (coerce -> path) -> mkNixStringWithSingletonContext (StringContext (DerivationOutput out) drvPath) path) (outputs drv') drvPathWithContext = mkNixStringWithSingletonContext (StringContext AllOutputs drvPath) drvPath - attrSet = mkNVStr <$> M.fromList (("drvPath", drvPathWithContext) : Map.toList outputsWithContext) + attrSet = NVStr <$> M.fromList (("drvPath", drvPathWithContext) : Map.toList outputsWithContext) -- TODO: Add location information for all the entries. -- here --v - pure $ mkNVSet mempty $ M.mapKeys coerce attrSet + pure $ NVSet mempty $ M.mapKeys coerce attrSet where @@ -368,7 +368,7 @@ buildDerivationWithContext drvAttrs = do env <- if useJson then do - jsonString :: NixString <- lift $ toJSONNixString $ mkNVSet mempty $ M.mapKeys coerce $ + jsonString :: NixString <- lift $ toJSONNixString $ NVSet mempty $ M.mapKeys coerce $ deleteKeys [ "args", "__ignoreNulls", "__structuredAttrs" ] attrs rawString :: Text <- extractNixString jsonString pure $ one ("__json", rawString) diff --git a/src/Nix/Exec.hs b/src/Nix/Exec.hs index 3f9dc07e8..53f5dc23f 100644 --- a/src/Nix/Exec.hs +++ b/src/Nix/Exec.hs @@ -61,7 +61,7 @@ mkNVConstantWithProvenance -> NAtom -> NValue t f m mkNVConstantWithProvenance scopes span x = - addProvenance (Provenance scopes . NConstantAnnF span $ x) $ mkNVConstant x + addProvenance (Provenance scopes . NConstantAnnF span $ x) $ NVConstant x mkNVStrWithProvenance :: MonadCited t f m @@ -70,7 +70,7 @@ mkNVStrWithProvenance -> NixString -> NValue t f m mkNVStrWithProvenance scopes span x = - addProvenance (Provenance scopes . NStrAnnF span . DoubleQuoted . one . Plain . ignoreContext $ x) $ mkNVStr x + addProvenance (Provenance scopes . NStrAnnF span . DoubleQuoted . one . Plain . ignoreContext $ x) $ NVStr x mkNVPathWithProvenance :: MonadCited t f m @@ -80,7 +80,7 @@ mkNVPathWithProvenance -> Path -> NValue t f m mkNVPathWithProvenance scope span lit real = - addProvenance (Provenance scope . NLiteralPathAnnF span $ lit) $ mkNVPath real + addProvenance (Provenance scope . NLiteralPathAnnF span $ lit) $ NVPath real mkNVClosureWithProvenance :: MonadCited t f m @@ -90,7 +90,7 @@ mkNVClosureWithProvenance -> (NValue t f m -> m (NValue t f m)) -> NValue t f m mkNVClosureWithProvenance scopes span x f = - addProvenance (Provenance scopes $ NAbsAnnF span (Nothing <$ x) Nothing) $ mkNVClosure x f + addProvenance (Provenance scopes $ NAbsAnnF span (Nothing <$ x) Nothing) $ NVClosure x f mkNVUnaryOpWithProvenance :: MonadCited t f m @@ -339,7 +339,7 @@ execUnaryOp scope span op arg = throwError $ ErrorCall $ "argument to unary operator must evaluate to an atomic type: " <> show _x where mkUnaryOp :: (a -> NAtom) -> (a -> a) -> a -> m (NValue t f m) - mkUnaryOp c b a = pure . mkNVUnaryOpWithProvenance scope span op (pure arg) . mkNVConstant $ c (b a) + mkUnaryOp c b a = pure . mkNVUnaryOpWithProvenance scope span op (pure arg) . NVConstant $ c (b a) execBinaryOp :: forall e t f m @@ -390,7 +390,7 @@ execBinaryOp scope span op lval rarg = toBoolOp :: Maybe (NValue t f m) -> Bool -> m (NValue t f m) toBoolOp r b = - pure $ mkNVBinaryOpWithProvenance scope span op (pure lval) r $ mkNVConstant $ NBool b + pure $ mkNVBinaryOpWithProvenance scope span op (pure lval) r $ NVConstant $ NBool b execBinaryOpForced :: forall e t f m @@ -454,25 +454,25 @@ execBinaryOpForced scope span op lval rval = mkNVBinaryOpWithProvenance scope span op (pure lval) (pure rval) mkBoolP :: Bool -> m (NValue t f m) - mkBoolP = pure . addProv . mkNVConstant . NBool + mkBoolP = pure . addProv . NVConstant . NBool mkIntP :: Integer -> m (NValue t f m) - mkIntP = pure . addProv . mkNVConstant . NInt + mkIntP = pure . addProv . NVConstant . NInt mkFloatP :: Float -> m (NValue t f m) - mkFloatP = pure . addProv . mkNVConstant . NFloat + mkFloatP = pure . addProv . NVConstant . NFloat mkListP :: [NValue t f m] -> NValue t f m - mkListP = addProv . mkNVList + mkListP = addProv . NVList mkStrP :: NixString -> NValue t f m - mkStrP = addProv . mkNVStr + mkStrP = addProv . NVStr mkPathP :: Path -> NValue t f m - mkPathP = addProv . mkNVPath + mkPathP = addProv . NVPath mkSetP :: (PositionSet -> AttrSet (NValue t f m) -> NValue t f m) - mkSetP x s = addProv $ mkNVSet x s + mkSetP x s = addProv $ NVSet x s mkCmpOp :: (forall a. Ord a => a -> a -> Bool) -> m (NValue t f m) mkCmpOp op = case (lval, rval) of diff --git a/src/Nix/Normal.hs b/src/Nix/Normal.hs index 53e22691e..f9324d25a 100644 --- a/src/Nix/Normal.hs +++ b/src/Nix/Normal.hs @@ -141,7 +141,7 @@ normalForm_ -> m () normalForm_ t = void $ normalizeValue t -opaqueVal :: Applicative f => NValue t f m +opaqueVal :: NvConstraint f => NValue t f m opaqueVal = mkNVStrWithoutContext "" -- | Detect cycles & stub them. @@ -167,14 +167,14 @@ stubCycles = where Free (NValue' cyc) = opaqueVal -thunkStubVal :: Applicative f => NValue t f m +thunkStubVal :: NvConstraint f => NValue t f m thunkStubVal = mkNVStrWithoutContext thunkStubText -- | Check if thunk @t@ is computed, -- then bind it into first arg. -- else bind the thunk stub val. bindComputedThunkOrStub - :: ( Applicative f + :: ( NvConstraint f , MonadThunk t m (NValue t f m) ) => (NValue t f m -> m a) diff --git a/src/Nix/Value.hs b/src/Nix/Value.hs index aafdc25a5..410528646 100644 --- a/src/Nix/Value.hs +++ b/src/Nix/Value.hs @@ -43,6 +43,7 @@ import Nix.String import Nix.Thunk + -- * @__NValueF__@: Base functor (F) -- | An NValueF p m r represents all the possible types of Nix values. @@ -266,6 +267,7 @@ hoistNValueF lft = -- * @__NValue'__@: forming the (F(A)) +type NvConstraint f = (Comonad f, Applicative f) -- | At the time of constructor, the expected arguments to closures are values -- that may contain thunks. The type of such thunks are fixed at that time. newtype NValue' t f m a = @@ -282,7 +284,7 @@ instance (Comonad f, Show a) => Show (NValue' t f m a) where -- ** Show1 -instance Comonad f => Show1 (NValue' t f m) where +instance NvConstraint f => Show1 (NValue' t f m) where liftShowsPrec sp sl p = \case NVConstant' atom -> showsUnaryWith showsPrec "NVConstantF" p atom NVStr' ns -> showsUnaryWith showsPrec "NVStrF" p $ ignoreContext ns @@ -398,66 +400,7 @@ unliftNValue' = hoistNValue' lift -- -- Facts of which are seen below: - --- | Haskell constant to the Nix constant, -mkNVConstant' :: Applicative f - => NAtom - -> NValue' t f m r -mkNVConstant' = NValue' . pure . NVConstantF - --- | Using of Nulls is generally discouraged (in programming language design et al.), but, if you need it. -nvNull' :: Applicative f - => NValue' t f m r -nvNull' = mkNVConstant' NNull - - --- | Haskell text & context to the Nix text & context, -mkNVStr' :: Applicative f - => NixString - -> NValue' t f m r -mkNVStr' = NValue' . pure . NVStrF - - --- | Haskell @Path@ to the Nix path, -mkNVPath' :: Applicative f - => Path - -> NValue' t f m r -mkNVPath' = NValue' . pure . NVPathF . coerce - - --- | Haskell @[]@ to the Nix @[]@, -mkNVList' :: Applicative f - => [r] - -> NValue' t f m r -mkNVList' = NValue' . pure . NVListF - - -- | Haskell key-value to the Nix key-value, -mkNVSet' :: Applicative f - => PositionSet - -> AttrSet r - -> NValue' t f m r -mkNVSet' p s = NValue' $ pure $ NVSetF p s - - --- | Haskell closure to the Nix closure, -mkNVClosure' :: (Applicative f, Functor m) - => Params () - -> (NValue t f m - -> m r - ) - -> NValue' t f m r -mkNVClosure' x f = NValue' $ pure $ NVClosureF x f - - --- | Haskell functions to the Nix functions! -mkNVBuiltin' :: (Applicative f, Functor m) - => VarName - -> (NValue t f m -> m r) - -> NValue' t f m r -mkNVBuiltin' name f = NValue' $ pure $ NVBuiltinF name f - - -- So above we have maps of Hask subcategory objects to Nix objects, -- and Hask subcategory morphisms to Nix morphisms. @@ -470,13 +413,36 @@ mkNVBuiltin' name f = NValue' $ pure $ NVBuiltinF name f -- the @NValueF a@. Which is @NValueF p m r@. Since it extracted from the -- @NValue@, which is formed by \( (F a -> a) F a \) in the first place. -- So @NValueF p m r@ which is extracted here, internally holds the next NValue. + +-- | Using of Nulls is generally discouraged (in programming language design et al.), but, if you need it. +pattern NVNull' = NVConstant' NNull +pattern NVConstant' :: NvConstraint w => NAtom -> NValue' t w m a pattern NVConstant' x <- NValue' (extract -> NVConstantF x) + where NVConstant' = NValue' . pure . NVConstantF + +pattern NVStr' :: NvConstraint w => NixString -> NValue' t w m a pattern NVStr' ns <- NValue' (extract -> NVStrF ns) + where NVStr' = NValue' . pure . NVStrF + +pattern NVPath' :: NvConstraint w => Path -> NValue' t w m a pattern NVPath' x <- NValue' (extract -> NVPathF x) + where NVPath' = NValue' . pure . NVPathF . coerce + +pattern NVList' :: NvConstraint w => [a] -> NValue' t w m a pattern NVList' l <- NValue' (extract -> NVListF l) + where NVList' = NValue' . pure . NVListF + +pattern NVSet' :: NvConstraint w => PositionSet -> AttrSet a -> NValue' t w m a pattern NVSet' p s <- NValue' (extract -> NVSetF p s) + where NVSet' p s = NValue' $ pure $ NVSetF p s + +pattern NVClosure' :: NvConstraint w => Params () -> (NValue t w m -> m a) -> NValue' t w m a pattern NVClosure' x f <- NValue' (extract -> NVClosureF x f) + where NVClosure' x f = NValue' $ pure $ NVClosureF x f + +pattern NVBuiltin' :: NvConstraint w => VarName -> (NValue t w m -> m a) -> NValue' t w m a pattern NVBuiltin' name f <- NValue' (extract -> NVBuiltinF name f) + where NVBuiltin' name f = NValue' $ pure $ NVBuiltinF name f {-# complete NVConstant', NVStr', NVPath', NVList', NVSet', NVClosure', NVBuiltin' #-} @@ -574,72 +540,12 @@ unliftNValue = hoistNValue lift -- The morphisms of the functor @Hask → NValue@. -- Continuation of the mantra: "Nix.Value#mantra" - --- | Life of a Haskell thunk to the life of a Nix thunk, -mkNVThunk :: Applicative f - => t - -> NValue t f m -mkNVThunk = Pure - - --- | Life of a Haskell constant to the life of a Nix constant, -mkNVConstant :: Applicative f - => NAtom - -> NValue t f m -mkNVConstant = Free . mkNVConstant' - -- | Using of Nulls is generally discouraged (in programming language design et al.), but, if you need it. -nvNull :: Applicative f - => NValue t f m -nvNull = mkNVConstant NNull --- | Life of a Haskell sting & context to the life of a Nix string & context, -mkNVStr :: Applicative f - => NixString - -> NValue t f m -mkNVStr = Free . mkNVStr' - -mkNVStrWithoutContext :: Applicative f +mkNVStrWithoutContext :: NvConstraint f => Text -> NValue t f m -mkNVStrWithoutContext = mkNVStr . mkNixStringWithoutContext - - --- | Life of a Haskell FilePath to the life of a Nix path -mkNVPath :: Applicative f - => Path - -> NValue t f m -mkNVPath = Free . mkNVPath' - - -mkNVList :: Applicative f - => [NValue t f m] - -> NValue t f m -mkNVList = Free . mkNVList' - - -mkNVSet :: Applicative f - => PositionSet - -> AttrSet (NValue t f m) - -> NValue t f m -mkNVSet p s = Free $ mkNVSet' p s - -mkNVClosure :: (Applicative f, Functor m) - => Params () - -> (NValue t f m - -> m (NValue t f m) - ) - -> NValue t f m -mkNVClosure x f = Free $ mkNVClosure' x f - - -mkNVBuiltin :: (Applicative f, Functor m) - => VarName - -> (NValue t f m - -> m (NValue t f m) - ) - -> NValue t f m -mkNVBuiltin name f = Free $ mkNVBuiltin' name f +mkNVStrWithoutContext = NVStr . mkNixStringWithoutContext builtin @@ -650,7 +556,7 @@ builtin -> m (NValue t f m) ) -- ^ unary function -> m (NValue t f m) -builtin = (pure .) . mkNVBuiltin +builtin = (pure .) . NVBuiltin builtin2 @@ -680,20 +586,22 @@ builtin3 = -- *** @F: Evaluation -> NValue@ -pattern NVThunk t <- Pure t -pattern NVValue v <- Free v -{-# complete NVThunk, NVValue #-} -pattern NVConstant x <- Free (NVConstant' x) -pattern NVStr ns <- Free (NVStr' ns) -pattern NVPath x <- Free (NVPath' x) -pattern NVList l <- Free (NVList' l) -pattern NVSet s x <- Free (NVSet' s x) -pattern NVClosure x f <- Free (NVClosure' x f) -pattern NVBuiltin name f <- Free (NVBuiltin' name f) +pattern NVNull = Free NVNull' +pattern NVThunk t = Pure t +pattern NVValue v = Free v +{-# complete NVThunk, NVValue, NVNull #-} +pattern NVConstant x = Free (NVConstant' x) +pattern NVStr ns = Free (NVStr' ns) +pattern NVPath x = Free (NVPath' x) +pattern NVList l = Free (NVList' l) +pattern NVSet s x = Free (NVSet' s x) +pattern NVClosure x f = Free (NVClosure' x f) +pattern NVBuiltin name f = Free (NVBuiltin' name f) {-# complete NVThunk, NVConstant, NVStr, NVPath, NVList, NVSet, NVClosure, NVBuiltin #-} + -- * @TStringContext@ data TStringContext = NoContext | HasContext @@ -784,7 +692,7 @@ data ValueFrame t f m | Expectation ValueType (NValue t f m) deriving Typeable -deriving instance (Comonad f, Show t) => Show (ValueFrame t f m) +deriving instance (NvConstraint f, Show t) => Show (ValueFrame t f m) -- * @MonadDataContext@ diff --git a/src/Nix/Value/Equal.hs b/src/Nix/Value/Equal.hs index 556d9d182..82f3643da 100644 --- a/src/Nix/Value/Equal.hs +++ b/src/Nix/Value/Equal.hs @@ -167,7 +167,7 @@ compareAttrSets f eq lm rm = runIdentity $ compareAttrSetsM (Identity . f) ((Identity .) . eq) lm rm valueEqM - :: (MonadThunk t m (NValue t f m), Comonad f) + :: (MonadThunk t m (NValue t f m), NvConstraint f) => NValue t f m -> NValue t f m -> m Bool @@ -195,7 +195,7 @@ valueEqM (Free (NValue' (extract -> x))) (Free (NValue' (extract -> y))) = _ -> mempty ) -thunkEqM :: (MonadThunk t m (NValue t f m), Comonad f) => t -> t -> m Bool +thunkEqM :: (MonadThunk t m (NValue t f m), NvConstraint f) => t -> t -> m Bool thunkEqM lt rt = do lv <- force lt From 7cd5ff35ccf3fc51930b9a50c6495d1276d33dd4 Mon Sep 17 00:00:00 2001 From: soulomoon Date: Sat, 22 Jan 2022 00:29:03 +0000 Subject: [PATCH 02/12] fix --- src/Nix/Builtins.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nix/Builtins.hs b/src/Nix/Builtins.hs index 28db89f15..d62cf784c 100644 --- a/src/Nix/Builtins.hs +++ b/src/Nix/Builtins.hs @@ -915,7 +915,7 @@ pathNix arg = Right (coerce . toText . coerce @StorePath @String -> s) <- addToStore name path recursive False -- TODO: Ensure that s matches sha256 when not empty - pure $ mkNVStr $ mkNixStringWithSingletonContext (StringContext DirectPath s) s + pure $ NVStr $ mkNixStringWithSingletonContext (StringContext DirectPath s) s where coerceToPath = coerceToString callFunc DontCopyToStore CoerceAny From 982ca3850e6b7c28853377758f431024b1e639dd Mon Sep 17 00:00:00 2001 From: soulomoon Date: Sat, 22 Jan 2022 00:44:32 +0000 Subject: [PATCH 03/12] fix --- src/Nix/Builtins.hs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Nix/Builtins.hs b/src/Nix/Builtins.hs index d62cf784c..e0dfd3757 100644 --- a/src/Nix/Builtins.hs +++ b/src/Nix/Builtins.hs @@ -33,10 +33,10 @@ import qualified "hashing" Crypto.Hash.SHA1 as SHA1 import qualified "hashing" Crypto.Hash.SHA256 as SHA256 import qualified "hashing" Crypto.Hash.SHA512 as SHA512 import qualified Data.Aeson as A - - - - +#if MIN_VERSION_aeson(2,0,0) +import qualified Data.Aeson.Key as AKM +import qualified Data.Aeson.KeyMap as AKM +#endif import Data.Align ( alignWith ) import Data.Array import Data.Bits @@ -1619,11 +1619,11 @@ fromJSONNix nvjson = A.Object m -> traverseToNValue (NVSet mempty) - - - +#if MIN_VERSION_aeson(2,0,0) + (M.mapKeys (coerce . AKM.toText) $ AKM.toHashMap m) +#else (M.mapKeys coerce m) - +#endif A.Array l -> traverseToNValue NVList (V.toList l) A.String s -> pure $ mkNVStrWithoutContext s A.Number n -> From 75347e699ffe8eef0b488e4dc4377a9477f8d8f6 Mon Sep 17 00:00:00 2001 From: soulomoon Date: Sat, 22 Jan 2022 00:59:10 +0000 Subject: [PATCH 04/12] add back bytestring version check --- src/Nix/Builtins.hs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Nix/Builtins.hs b/src/Nix/Builtins.hs index e0dfd3757..69cd81ecb 100644 --- a/src/Nix/Builtins.hs +++ b/src/Nix/Builtins.hs @@ -1530,14 +1530,14 @@ placeHolderNix p = $ Base32.encode -- Please, stop Text -> Bytestring here after migration to Text $ case Base16.decode (bytes h) of -- The result coming out of hashString is base16 encoded - +#if MIN_VERSION_base16_bytestring(1,0,0) -- Please, stop Text -> String here after migration to Text Left e -> error $ "Couldn't Base16 decode the text: '" <> body h <> "'.\nThe Left fail content: '" <> show e <> "'." Right d -> d - - - - +#else + (d, "") -> d + (_, e) -> error $ "Couldn't Base16 decode the text: '" <> body h <> "'.\nUndecodable remainder: '" <> show e <> "'." +#endif where bytes :: NixString -> ByteString bytes = encodeUtf8 . body From 59cd27d8fc8a133ddb3bb46c24a61092766c90b0 Mon Sep 17 00:00:00 2001 From: soulomoon Date: Sun, 23 Jan 2022 22:36:26 +0800 Subject: [PATCH 05/12] rename NvConstraint to NVConstraint --- src/Nix/Builtins.hs | 6 +++--- src/Nix/Normal.hs | 6 +++--- src/Nix/Value.hs | 26 ++++++++++++++------------ src/Nix/Value/Equal.hs | 4 ++-- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/Nix/Builtins.hs b/src/Nix/Builtins.hs index 69cd81ecb..d1dc55150 100644 --- a/src/Nix/Builtins.hs +++ b/src/Nix/Builtins.hs @@ -132,7 +132,7 @@ instance -- We wrap values solely to provide an Ord instance for genericClosure data WValue t f m where - WValue :: NvConstraint f => NValue t f m -> WValue t f m + WValue :: NVConstraint f => NValue t f m -> WValue t f m instance Eq (WValue t f m) where WValue (NVConstant (NFloat x)) == WValue (NVConstant (NInt y)) = @@ -337,7 +337,7 @@ splitMatches numDropped (((_, (start, len)) : captures) : mts) haystack = (thunkStr a) (s >= 0) -thunkStr :: NvConstraint f => ByteString -> NValue t f m +thunkStr :: NVConstraint f => ByteString -> NValue t f m thunkStr s = mkNVStrWithoutContext $ decodeUtf8 s hasKind @@ -1785,7 +1785,7 @@ currentTimeNix = derivationStrictNix :: MonadNix e t f m => NValue t f m -> m (NValue t f m) derivationStrictNix = derivationStrict -getRecursiveSizeNix :: (MonadIntrospect m, NvConstraint f) => a -> m (NValue t f m) +getRecursiveSizeNix :: (MonadIntrospect m, NVConstraint f) => a -> m (NValue t f m) getRecursiveSizeNix = fmap (NVConstant . NInt . fromIntegral) . recursiveSize getContextNix diff --git a/src/Nix/Normal.hs b/src/Nix/Normal.hs index f9324d25a..4651a2e55 100644 --- a/src/Nix/Normal.hs +++ b/src/Nix/Normal.hs @@ -141,7 +141,7 @@ normalForm_ -> m () normalForm_ t = void $ normalizeValue t -opaqueVal :: NvConstraint f => NValue t f m +opaqueVal :: NVConstraint f => NValue t f m opaqueVal = mkNVStrWithoutContext "" -- | Detect cycles & stub them. @@ -167,14 +167,14 @@ stubCycles = where Free (NValue' cyc) = opaqueVal -thunkStubVal :: NvConstraint f => NValue t f m +thunkStubVal :: NVConstraint f => NValue t f m thunkStubVal = mkNVStrWithoutContext thunkStubText -- | Check if thunk @t@ is computed, -- then bind it into first arg. -- else bind the thunk stub val. bindComputedThunkOrStub - :: ( NvConstraint f + :: ( NVConstraint f , MonadThunk t m (NValue t f m) ) => (NValue t f m -> m a) diff --git a/src/Nix/Value.hs b/src/Nix/Value.hs index 410528646..9ef30cb87 100644 --- a/src/Nix/Value.hs +++ b/src/Nix/Value.hs @@ -267,7 +267,6 @@ hoistNValueF lft = -- * @__NValue'__@: forming the (F(A)) -type NvConstraint f = (Comonad f, Applicative f) -- | At the time of constructor, the expected arguments to closures are values -- that may contain thunks. The type of such thunks are fixed at that time. newtype NValue' t f m a = @@ -282,9 +281,9 @@ instance (Comonad f, Show a) => Show (NValue' t f m a) where show (NValue' (extract -> v)) = show v --- ** Show1 +-- ** NVConstraint -instance NvConstraint f => Show1 (NValue' t f m) where +instance NVConstraint f => Show1 (NValue' t f m) where liftShowsPrec sp sl p = \case NVConstant' atom -> showsUnaryWith showsPrec "NVConstantF" p atom NVStr' ns -> showsUnaryWith showsPrec "NVStrF" p $ ignoreContext ns @@ -380,6 +379,9 @@ unliftNValue' = hoistNValue' lift -- ** Bijective Hask subcategory <-> @NValue'@ + +type NVConstraint f = (Comonad f, Applicative f) + -- *** @F: Hask subcategory → NValue'@ -- -- #mantra# @@ -416,31 +418,31 @@ unliftNValue' = hoistNValue' lift -- | Using of Nulls is generally discouraged (in programming language design et al.), but, if you need it. pattern NVNull' = NVConstant' NNull -pattern NVConstant' :: NvConstraint w => NAtom -> NValue' t w m a +pattern NVConstant' :: NVConstraint w => NAtom -> NValue' t w m a pattern NVConstant' x <- NValue' (extract -> NVConstantF x) where NVConstant' = NValue' . pure . NVConstantF -pattern NVStr' :: NvConstraint w => NixString -> NValue' t w m a +pattern NVStr' :: NVConstraint w => NixString -> NValue' t w m a pattern NVStr' ns <- NValue' (extract -> NVStrF ns) where NVStr' = NValue' . pure . NVStrF -pattern NVPath' :: NvConstraint w => Path -> NValue' t w m a +pattern NVPath' :: NVConstraint w => Path -> NValue' t w m a pattern NVPath' x <- NValue' (extract -> NVPathF x) where NVPath' = NValue' . pure . NVPathF . coerce -pattern NVList' :: NvConstraint w => [a] -> NValue' t w m a +pattern NVList' :: NVConstraint w => [a] -> NValue' t w m a pattern NVList' l <- NValue' (extract -> NVListF l) where NVList' = NValue' . pure . NVListF -pattern NVSet' :: NvConstraint w => PositionSet -> AttrSet a -> NValue' t w m a +pattern NVSet' :: NVConstraint w => PositionSet -> AttrSet a -> NValue' t w m a pattern NVSet' p s <- NValue' (extract -> NVSetF p s) where NVSet' p s = NValue' $ pure $ NVSetF p s -pattern NVClosure' :: NvConstraint w => Params () -> (NValue t w m -> m a) -> NValue' t w m a +pattern NVClosure' :: NVConstraint w => Params () -> (NValue t w m -> m a) -> NValue' t w m a pattern NVClosure' x f <- NValue' (extract -> NVClosureF x f) where NVClosure' x f = NValue' $ pure $ NVClosureF x f -pattern NVBuiltin' :: NvConstraint w => VarName -> (NValue t w m -> m a) -> NValue' t w m a +pattern NVBuiltin' :: NVConstraint w => VarName -> (NValue t w m -> m a) -> NValue' t w m a pattern NVBuiltin' name f <- NValue' (extract -> NVBuiltinF name f) where NVBuiltin' name f = NValue' $ pure $ NVBuiltinF name f {-# complete NVConstant', NVStr', NVPath', NVList', NVSet', NVClosure', NVBuiltin' #-} @@ -542,7 +544,7 @@ unliftNValue = hoistNValue lift -- | Using of Nulls is generally discouraged (in programming language design et al.), but, if you need it. -mkNVStrWithoutContext :: NvConstraint f +mkNVStrWithoutContext :: NVConstraint f => Text -> NValue t f m mkNVStrWithoutContext = NVStr . mkNixStringWithoutContext @@ -692,7 +694,7 @@ data ValueFrame t f m | Expectation ValueType (NValue t f m) deriving Typeable -deriving instance (NvConstraint f, Show t) => Show (ValueFrame t f m) +deriving instance (NVConstraint f, Show t) => Show (ValueFrame t f m) -- * @MonadDataContext@ diff --git a/src/Nix/Value/Equal.hs b/src/Nix/Value/Equal.hs index 82f3643da..d078e7544 100644 --- a/src/Nix/Value/Equal.hs +++ b/src/Nix/Value/Equal.hs @@ -167,7 +167,7 @@ compareAttrSets f eq lm rm = runIdentity $ compareAttrSetsM (Identity . f) ((Identity .) . eq) lm rm valueEqM - :: (MonadThunk t m (NValue t f m), NvConstraint f) + :: (MonadThunk t m (NValue t f m), NVConstraint f) => NValue t f m -> NValue t f m -> m Bool @@ -195,7 +195,7 @@ valueEqM (Free (NValue' (extract -> x))) (Free (NValue' (extract -> y))) = _ -> mempty ) -thunkEqM :: (MonadThunk t m (NValue t f m), NvConstraint f) => t -> t -> m Bool +thunkEqM :: (MonadThunk t m (NValue t f m), NVConstraint f) => t -> t -> m Bool thunkEqM lt rt = do lv <- force lt From 61514e7a376e7cab364bf695337ace1ff86c1883 Mon Sep 17 00:00:00 2001 From: soulomoon Date: Sun, 23 Jan 2022 23:23:51 +0800 Subject: [PATCH 06/12] adjust docuementation about the bijection between Hask subcategory <-> NValue' --- src/Nix/Value.hs | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/src/Nix/Value.hs b/src/Nix/Value.hs index 9ef30cb87..f38c7bf4c 100644 --- a/src/Nix/Value.hs +++ b/src/Nix/Value.hs @@ -43,7 +43,6 @@ import Nix.String import Nix.Thunk - -- * @__NValueF__@: Base functor (F) -- | An NValueF p m r represents all the possible types of Nix values. @@ -267,6 +266,12 @@ hoistNValueF lft = -- * @__NValue'__@: forming the (F(A)) +-- | NVConstraint constraint the f layer in @NValue'@. +-- It makes bijection between sub category of Hask and Nix Value possible. +-- 'Comonad' enable Nix Value to Hask part. +-- 'Applicative' enable Hask to Nix Value part. +type NVConstraint f = (Comonad f, Applicative f) + -- | At the time of constructor, the expected arguments to closures are values -- that may contain thunks. The type of such thunks are fixed at that time. newtype NValue' t f m a = @@ -277,11 +282,11 @@ newtype NValue' t f m a = } deriving (Generic, Typeable, Functor, Foldable) -instance (Comonad f, Show a) => Show (NValue' t f m a) where +instance (NVConstraint f, Show a) => Show (NValue' t f m a) where show (NValue' (extract -> v)) = show v --- ** NVConstraint +-- ** Show1 instance NVConstraint f => Show1 (NValue' t f m) where liftShowsPrec sp sl p = \case @@ -379,13 +384,9 @@ unliftNValue' = hoistNValue' lift -- ** Bijective Hask subcategory <-> @NValue'@ - -type NVConstraint f = (Comonad f, Applicative f) - --- *** @F: Hask subcategory → NValue'@ --- +-- *** @F: Hask subcategory <-> NValue'@ -- #mantra# --- $Methods @F: Hask → NValue'@ +-- $Patterns @F: Hask <-> NValue'@ -- -- Since Haskell and Nix are both recursive purely functional lazy languages. -- And since recursion-schemes. @@ -399,49 +400,54 @@ type NVConstraint f = (Comonad f, Applicative f) -- -- Since it is a proper way of scientific implementation, we would eventually form a -- lawful functor. --- --- Facts of which are seen below: - --- | Haskell key-value to the Nix key-value, --- So above we have maps of Hask subcategory objects to Nix objects, --- and Hask subcategory morphisms to Nix morphisms. - --- *** @F: NValue -> NValue'@ - --- | Module pattens use @language PatternSynonyms@: unidirectional synonyms (@<-@), +-- +-- Module pattens use @language PatternSynonyms@: bidirectional synonyms (@<-@), -- and @ViewPatterns@: (@->@) at the same time. -- @ViewPatterns Control.Comonad.extract@ extracts -- from the @NValue (Free (NValueF a))@ -- the @NValueF a@. Which is @NValueF p m r@. Since it extracted from the -- @NValue@, which is formed by \( (F a -> a) F a \) in the first place. -- So @NValueF p m r@ which is extracted here, internally holds the next NValue. +-- +-- Facts of bijection between Hask subcategory objects and Nix objects, +-- and between Hask subcategory morphisms and Nix morphisms are seen blow: + -- | Using of Nulls is generally discouraged (in programming language design et al.), but, if you need it. +pattern NVNull' :: NVConstraint w => NValue' t w m a pattern NVNull' = NVConstant' NNull + +-- | Haskell constant to the Nix constant, pattern NVConstant' :: NVConstraint w => NAtom -> NValue' t w m a pattern NVConstant' x <- NValue' (extract -> NVConstantF x) where NVConstant' = NValue' . pure . NVConstantF +-- | Haskell text & context to the Nix text & context, pattern NVStr' :: NVConstraint w => NixString -> NValue' t w m a pattern NVStr' ns <- NValue' (extract -> NVStrF ns) where NVStr' = NValue' . pure . NVStrF +-- | Haskell @Path@ to the Nix path, pattern NVPath' :: NVConstraint w => Path -> NValue' t w m a pattern NVPath' x <- NValue' (extract -> NVPathF x) where NVPath' = NValue' . pure . NVPathF . coerce +-- | Haskell @[]@ to the Nix @[]@, pattern NVList' :: NVConstraint w => [a] -> NValue' t w m a pattern NVList' l <- NValue' (extract -> NVListF l) where NVList' = NValue' . pure . NVListF +-- | Haskell key-value to the Nix key-value, pattern NVSet' :: NVConstraint w => PositionSet -> AttrSet a -> NValue' t w m a pattern NVSet' p s <- NValue' (extract -> NVSetF p s) where NVSet' p s = NValue' $ pure $ NVSetF p s +-- | Haskell closure to the Nix closure, pattern NVClosure' :: NVConstraint w => Params () -> (NValue t w m -> m a) -> NValue' t w m a pattern NVClosure' x f <- NValue' (extract -> NVClosureF x f) where NVClosure' x f = NValue' $ pure $ NVClosureF x f +-- | Haskell functions to the Nix functions! pattern NVBuiltin' :: NVConstraint w => VarName -> (NValue t w m -> m a) -> NValue' t w m a pattern NVBuiltin' name f <- NValue' (extract -> NVBuiltinF name f) where NVBuiltin' name f = NValue' $ pure $ NVBuiltinF name f From f15844f98423c0b444fe52f64321a6f10ab9adad Mon Sep 17 00:00:00 2001 From: soulomoon Date: Sun, 23 Jan 2022 23:57:17 +0800 Subject: [PATCH 07/12] update changelog for Nix.Value --- ChangeLog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index 6acf7737e..2d1553147 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -7,6 +7,8 @@ * `Nix.Expr.Types` * [(link)](https://github.com/haskell-nix/hnix/pull/1042/files) The central HNix type `NExprF` changed, the `NApp` was moved out of `NBinary` & now a `NExprF` constructor of its own, the type signatures were changed accordingly. * [(link)](https://github.com/haskell-nix/hnix/pull/1038/files) project was using `megaparsec` `{,Source}Pos` and to use it shipped a lot of orphan instances. To improve the situation & performance (reports [#1026](https://github.com/haskell-nix/hnix/issues/1026), [#746](https://github.com/haskell-nix/hnix/issues/746)) project uses `N{,Source}Pos` types, related type signatures were changed accordingly. + * `Nix.Value` + * Unify `mkNV*` and `NV*` patterns by bidirectional synonyms, a lot of `mkNV*` are removed, and merged to `NV*`. e.g. instead of `mkNVList`, `NVList` should be used, same goes for . ## [(diff)](https://github.com/haskell-nix/hnix/compare/0.15.0...0.16.0#files_bucket) 0.16.0 From 6cad5620fa322aab562bc8ce690ca996d4d68acf Mon Sep 17 00:00:00 2001 From: soulomoon Date: Mon, 24 Jan 2022 00:01:36 +0800 Subject: [PATCH 08/12] update changelog for Nix.Value in 0.17.0 --- ChangeLog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index 2d1553147..eb99c97a0 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -8,7 +8,7 @@ * [(link)](https://github.com/haskell-nix/hnix/pull/1042/files) The central HNix type `NExprF` changed, the `NApp` was moved out of `NBinary` & now a `NExprF` constructor of its own, the type signatures were changed accordingly. * [(link)](https://github.com/haskell-nix/hnix/pull/1038/files) project was using `megaparsec` `{,Source}Pos` and to use it shipped a lot of orphan instances. To improve the situation & performance (reports [#1026](https://github.com/haskell-nix/hnix/issues/1026), [#746](https://github.com/haskell-nix/hnix/issues/746)) project uses `N{,Source}Pos` types, related type signatures were changed accordingly. * `Nix.Value` - * Unify `mkNV*` and `NV*` patterns by bidirectional synonyms, a lot of `mkNV*` are removed, and merged to `NV*`. e.g. instead of `mkNVList`, `NVList` should be used, same goes for . + * Unify builder `mkNV*` and `NV*` patterns by bidirectional synonyms, a lot of builders `mkNV*` are removed, and merged to `NV*`. e.g. instead of builder `mkNVList`, `NVList` should be used. ## [(diff)](https://github.com/haskell-nix/hnix/compare/0.15.0...0.16.0#files_bucket) 0.16.0 From 35d25c631b1b46dbd9532ab470efa64adbd5d797 Mon Sep 17 00:00:00 2001 From: soulomoon Date: Mon, 24 Jan 2022 00:12:42 +0800 Subject: [PATCH 09/12] update changelog add Nix.Value.NVConstraint section in 0.17.0 --- ChangeLog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index eb99c97a0..a96e9adce 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -9,6 +9,8 @@ * [(link)](https://github.com/haskell-nix/hnix/pull/1038/files) project was using `megaparsec` `{,Source}Pos` and to use it shipped a lot of orphan instances. To improve the situation & performance (reports [#1026](https://github.com/haskell-nix/hnix/issues/1026), [#746](https://github.com/haskell-nix/hnix/issues/746)) project uses `N{,Source}Pos` types, related type signatures were changed accordingly. * `Nix.Value` * Unify builder `mkNV*` and `NV*` patterns by bidirectional synonyms, a lot of builders `mkNV*` are removed, and merged to `NV*`. e.g. instead of builder `mkNVList`, `NVList` should be used. + * Constraint `NVConstraint f = (Comonad f, Applicative f)` was introduced, in order to unify builder `mkNV*` and `NV*` patterns. + ## [(diff)](https://github.com/haskell-nix/hnix/compare/0.15.0...0.16.0#files_bucket) 0.16.0 From 0bb030ae509d28c4475c536f4a17af077dfc3da0 Mon Sep 17 00:00:00 2001 From: soulomoon Date: Mon, 24 Jan 2022 00:14:55 +0800 Subject: [PATCH 10/12] update changelog add link to Nix.Value section in 0.17.0 --- ChangeLog.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index a96e9adce..0c62ef754 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -8,8 +8,8 @@ * [(link)](https://github.com/haskell-nix/hnix/pull/1042/files) The central HNix type `NExprF` changed, the `NApp` was moved out of `NBinary` & now a `NExprF` constructor of its own, the type signatures were changed accordingly. * [(link)](https://github.com/haskell-nix/hnix/pull/1038/files) project was using `megaparsec` `{,Source}Pos` and to use it shipped a lot of orphan instances. To improve the situation & performance (reports [#1026](https://github.com/haskell-nix/hnix/issues/1026), [#746](https://github.com/haskell-nix/hnix/issues/746)) project uses `N{,Source}Pos` types, related type signatures were changed accordingly. * `Nix.Value` - * Unify builder `mkNV*` and `NV*` patterns by bidirectional synonyms, a lot of builders `mkNV*` are removed, and merged to `NV*`. e.g. instead of builder `mkNVList`, `NVList` should be used. - * Constraint `NVConstraint f = (Comonad f, Applicative f)` was introduced, in order to unify builder `mkNV*` and `NV*` patterns. + * [(link)](https://github.com/haskell-nix/hnix/pull/1046/files) Unify builder `mkNV*` and `NV*` patterns by bidirectional synonyms, a lot of builders `mkNV*` are removed, and merged to `NV*`. e.g. instead of builder `mkNVList`, `NVList` should be used. + * [(link)](https://github.com/haskell-nix/hnix/pull/1046/files) Constraint `NVConstraint f = (Comonad f, Applicative f)` was introduced, in order to unify builder `mkNV*` and `NV*` patterns. ## [(diff)](https://github.com/haskell-nix/hnix/compare/0.15.0...0.16.0#files_bucket) 0.16.0 From 26e28e56ad5313c8aa9eaed27031880d3cfd0142 Mon Sep 17 00:00:00 2001 From: soulomoon Date: Mon, 24 Jan 2022 00:47:27 +0800 Subject: [PATCH 11/12] update changelog adjust Nix.Value section in 0.17.0 --- ChangeLog.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index 0c62ef754..1be0ec1d2 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -3,13 +3,16 @@ ## [(diff)](https://github.com/haskell-nix/hnix/compare/0.16.0...0.17.0#files_bucket) 0.17.0 +* Introduction: + * `Nix.Value` + * [(link)](https://github.com/haskell-nix/hnix/pull/1046/files) Constraint `NVConstraint f = (Comonad f, Applicative f)` was introduced, in order to unify builder `mkNV*` and `NV*` patterns. + * Breaking: * `Nix.Expr.Types` * [(link)](https://github.com/haskell-nix/hnix/pull/1042/files) The central HNix type `NExprF` changed, the `NApp` was moved out of `NBinary` & now a `NExprF` constructor of its own, the type signatures were changed accordingly. * [(link)](https://github.com/haskell-nix/hnix/pull/1038/files) project was using `megaparsec` `{,Source}Pos` and to use it shipped a lot of orphan instances. To improve the situation & performance (reports [#1026](https://github.com/haskell-nix/hnix/issues/1026), [#746](https://github.com/haskell-nix/hnix/issues/746)) project uses `N{,Source}Pos` types, related type signatures were changed accordingly. * `Nix.Value` * [(link)](https://github.com/haskell-nix/hnix/pull/1046/files) Unify builder `mkNV*` and `NV*` patterns by bidirectional synonyms, a lot of builders `mkNV*` are removed, and merged to `NV*`. e.g. instead of builder `mkNVList`, `NVList` should be used. - * [(link)](https://github.com/haskell-nix/hnix/pull/1046/files) Constraint `NVConstraint f = (Comonad f, Applicative f)` was introduced, in order to unify builder `mkNV*` and `NV*` patterns. ## [(diff)](https://github.com/haskell-nix/hnix/compare/0.15.0...0.16.0#files_bucket) 0.16.0 From 3b2d3deff811378e98f901069a9131ef2b8102f3 Mon Sep 17 00:00:00 2001 From: soulomoon Date: Mon, 24 Jan 2022 02:47:38 +0800 Subject: [PATCH 12/12] remove GADTs language extension for performance --- src/Nix/Builtins.hs | 9 ++++----- src/Nix/Lint.hs | 1 - src/Nix/Normal.hs | 1 - src/Nix/Render.hs | 1 - src/Nix/Render/Frame.hs | 1 - 5 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/Nix/Builtins.hs b/src/Nix/Builtins.hs index d1dc55150..65655e000 100644 --- a/src/Nix/Builtins.hs +++ b/src/Nix/Builtins.hs @@ -1,9 +1,9 @@ -{-# LANGUAGE GADTs #-} {-# language CPP #-} {-# language AllowAmbiguousTypes #-} {-# language ConstraintKinds #-} {-# language FunctionalDependencies #-} {-# language KindSignatures #-} +{-# language MonoLocalBinds #-} {-# language MultiWayIf #-} {-# language PartialTypeSignatures #-} {-# language QuasiQuotes #-} @@ -131,10 +131,9 @@ instance -- *** @WValue@ closure wrapper to have @Ord@ -- We wrap values solely to provide an Ord instance for genericClosure -data WValue t f m where - WValue :: NVConstraint f => NValue t f m -> WValue t f m +newtype WValue t f m = WValue (NValue t f m) -instance Eq (WValue t f m) where +instance NVConstraint f => Eq (WValue t f m) where WValue (NVConstant (NFloat x)) == WValue (NVConstant (NInt y)) = x == fromInteger y WValue (NVConstant (NInt x)) == WValue (NVConstant (NFloat y)) = @@ -146,7 +145,7 @@ instance Eq (WValue t f m) where ignoreContext x == ignoreContext y _ == _ = False -instance Ord (WValue t f m) where +instance NVConstraint f => Ord (WValue t f m) where WValue (NVConstant (NFloat x)) <= WValue (NVConstant (NInt y)) = x <= fromInteger y WValue (NVConstant (NInt x)) <= WValue (NVConstant (NFloat y)) = diff --git a/src/Nix/Lint.hs b/src/Nix/Lint.hs index 54c8f7b81..3fa34c88c 100644 --- a/src/Nix/Lint.hs +++ b/src/Nix/Lint.hs @@ -1,7 +1,6 @@ {-# language ConstraintKinds #-} {-# language CPP #-} {-# language DataKinds #-} -{-# language GADTs #-} {-# language GeneralizedNewtypeDeriving #-} {-# language TypeFamilies #-} {-# language UndecidableInstances #-} diff --git a/src/Nix/Normal.hs b/src/Nix/Normal.hs index 4651a2e55..b9ae8f08c 100644 --- a/src/Nix/Normal.hs +++ b/src/Nix/Normal.hs @@ -1,7 +1,6 @@ {-# language AllowAmbiguousTypes #-} {-# language ConstraintKinds #-} {-# language DataKinds #-} -{-# language GADTs #-} {-# language TypeFamilies #-} {-# language RankNTypes #-} diff --git a/src/Nix/Render.hs b/src/Nix/Render.hs index 50fc17fdb..a31d5520b 100644 --- a/src/Nix/Render.hs +++ b/src/Nix/Render.hs @@ -2,7 +2,6 @@ {-# language CPP #-} {-# language ConstraintKinds #-} {-# language DefaultSignatures #-} -{-# language GADTs #-} {-# language TypeFamilies #-} {-# language TypeOperators #-} {-# language MultiWayIf #-} diff --git a/src/Nix/Render/Frame.hs b/src/Nix/Render/Frame.hs index a19942f83..175b71378 100644 --- a/src/Nix/Render/Frame.hs +++ b/src/Nix/Render/Frame.hs @@ -2,7 +2,6 @@ {-# language AllowAmbiguousTypes #-} {-# language ConstraintKinds #-} {-# language MultiWayIf #-} -{-# language GADTs #-} {-# language TypeFamilies #-}