From c23d22afcfecccb5bfe665a034cbc6bb4a8a5a31 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Mon, 22 Feb 2021 16:30:09 +0200 Subject: [PATCH 01/14] {Type.Infer, Standard}: add instance sigs to MonadValue instances Helps with further work. --- src/Nix/Standard.hs | 16 ++++++++++++++++ src/Nix/Type/Infer.hs | 18 ++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/Nix/Standard.hs b/src/Nix/Standard.hs index 18fc06cac..b512a6467 100644 --- a/src/Nix/Standard.hs +++ b/src/Nix/Standard.hs @@ -11,6 +11,7 @@ {-# LANGUAGE TypeApplications #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE InstanceSigs #-} {-# OPTIONS_GHC -Wno-orphans #-} @@ -139,11 +140,26 @@ instance ( MonadAtomicRef m , MonadThunkId m ) => MonadValue (StdValue m) m where + defer + :: m (StdValue m) + -> m (StdValue m) defer = fmap Pure . thunk + demand + :: StdValue m + -> ( StdValue m + -> m r + ) + -> m r demand (Pure v) f = force v (flip demand f) demand (Free v) f = f (Free v) + inform + :: StdValue m + -> ( m (StdValue m) + -> m (StdValue m) + ) + -> m (StdValue m) inform (Pure t) f = Pure <$> further t f inform (Free v) f = Free <$> bindNValue' id (flip inform f) v diff --git a/src/Nix/Type/Infer.hs b/src/Nix/Type/Infer.hs index 88a729811..3ad916741 100644 --- a/src/Nix/Type/Infer.hs +++ b/src/Nix/Type/Infer.hs @@ -15,6 +15,7 @@ {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeSynonymInstances #-} +{-# LANGUAGE InstanceSigs #-} {-# OPTIONS_GHC -Wno-name-shadowing #-} @@ -398,9 +399,26 @@ type MonadInfer m = ({- MonadThunkId m,-} MonadVar m, MonadFix m) +-- 2021-02-22: NOTE: Seems like suporflous instance instance Monad m => MonadValue (Judgment s) (InferT s m) where + defer + :: InferT s m (Judgment s) + -> InferT s m (Judgment s) defer = id + + demand + :: Judgment s + -> ( Judgment s + -> InferT s m r) + -> InferT s m r demand = flip ($) + + inform + :: Judgment s + -> ( InferT s m (Judgment s) + -> InferT s m (Judgment s) + ) + -> InferT s m (Judgment s) inform j f = f (pure j) {- From bbee9bd448d0f83c9982e6f11159bbebeff68eb3 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Mon, 22 Feb 2021 19:37:20 +0200 Subject: [PATCH 02/14] Thunk: unflip the `force{,Eff}` instances This is much more performant, sine gives tail recursion. Also gives more straight-forward code implementation. M src/Nix/Cited/Basic.hs M src/Nix/Convert.hs M src/Nix/Lint.hs M src/Nix/Normal.hs M src/Nix/Standard.hs M src/Nix/Thunk.hs M src/Nix/Thunk/Basic.hs M src/Nix/Value.hs M src/Nix/Value/Equal.hs --- src/Nix/Cited/Basic.hs | 12 ++++++------ src/Nix/Convert.hs | 8 ++++---- src/Nix/Lint.hs | 2 +- src/Nix/Normal.hs | 8 +++++--- src/Nix/Standard.hs | 6 +++--- src/Nix/Thunk.hs | 4 ++-- src/Nix/Thunk/Basic.hs | 10 +++++----- src/Nix/Value.hs | 2 +- src/Nix/Value/Equal.hs | 4 ++-- 9 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/Nix/Cited/Basic.hs b/src/Nix/Cited/Basic.hs index 935b8ecd1..84263eb48 100644 --- a/src/Nix/Cited/Basic.hs +++ b/src/Nix/Cited/Basic.hs @@ -80,21 +80,21 @@ instance ( Has e Options -- which does not capture the current stack frame information to provide -- it in a NixException, so we catch and re-throw it here using -- 'throwError' from Frames.hs. - force (Cited (NCited ps t)) f = + force f (Cited (NCited ps t)) = catch go (throwError @ThunkLoop) where go = case ps of - [] -> force t f + [] -> force f t Provenance scope e@(Compose (Ann s _)) : _ -> - withFrame Info (ForcingExpr scope (wrapExprLoc s e)) (force t f) + withFrame Info (ForcingExpr scope (wrapExprLoc s e)) (force f t) - forceEff (Cited (NCited ps t)) f = catch + forceEff f (Cited (NCited ps t)) = catch go (throwError @ThunkLoop) where go = case ps of - [] -> forceEff t f + [] -> forceEff f t Provenance scope e@(Compose (Ann s _)) : _ -> - withFrame Info (ForcingExpr scope (wrapExprLoc s e)) (forceEff t f) + withFrame Info (ForcingExpr scope (wrapExprLoc s e)) (forceEff f t) further (Cited (NCited ps t)) f = Cited . NCited ps <$> further t f diff --git a/src/Nix/Convert.hs b/src/Nix/Convert.hs index 9e2ec0d9e..f4a56f529 100644 --- a/src/Nix/Convert.hs +++ b/src/Nix/Convert.hs @@ -77,10 +77,10 @@ instance ( Convertible e t f m ) => FromValue a m (NValue t f m) where fromValueMay = flip demand $ \case - Pure t -> force t fromValueMay + Pure t -> force fromValueMay t Free v -> fromValueMay v fromValue = flip demand $ \case - Pure t -> force t fromValue + Pure t -> force fromValue t Free v -> fromValue v instance ( Convertible e t f m @@ -89,10 +89,10 @@ instance ( Convertible e t f m ) => FromValue a m (Deeper (NValue t f m)) where fromValueMay (Deeper v) = demand v $ \case - Pure t -> force t (fromValueMay . Deeper) + Pure t -> force (fromValueMay . Deeper) t Free v -> fromValueMay (Deeper v) fromValue (Deeper v) = demand v $ \case - Pure t -> force t (fromValue . Deeper) + Pure t -> force (fromValue . Deeper) t Free v -> fromValue (Deeper v) instance Convertible e t f m diff --git a/src/Nix/Lint.hs b/src/Nix/Lint.hs index 6dc53c803..470d0a06f 100644 --- a/src/Nix/Lint.hs +++ b/src/Nix/Lint.hs @@ -266,7 +266,7 @@ instance ToValue (AttrSet (Symbolic m), AttrSet SourcePos) m (Symbolic m) where instance (MonadThunkId m, MonadAtomicRef m, MonadCatch m) => MonadValue (Symbolic m) m where defer = fmap ST . thunk - demand (ST v) f = force v (flip demand f) + demand (ST v) f = force (`demand` f) v demand (SV v) f = f (SV v) instance MonadLint e m => MonadEval (Symbolic m) m where diff --git a/src/Nix/Normal.hs b/src/Nix/Normal.hs index 7ac490674..d767664b4 100644 --- a/src/Nix/Normal.hs +++ b/src/Nix/Normal.hs @@ -43,7 +43,7 @@ normalizeValue => (forall r . t -> (NValue t f m -> m r) -> m r) -> NValue t f m -> m (NValue t f m) -normalizeValue f = run . iterNValueM run go (fmap Free . sequenceNValue' run) +normalizeValue f tnk = run $ iterNValueM run go (fmap Free . sequenceNValue' run) tnk where start = 0 :: Int table = mempty @@ -84,7 +84,8 @@ normalForm ) => NValue t f m -> m (NValue t f m) -normalForm = fmap stubCycles . normalizeValue force +-- 2021-02-22: NOTE: `normalizeValue` should be adopted to work without flip, but currently was recieving infinite type. +normalForm t = stubCycles <$> (flip force `normalizeValue` t) normalForm_ :: ( Framed e m @@ -94,7 +95,8 @@ normalForm_ ) => NValue t f m -> m () -normalForm_ = void <$> normalizeValue forceEff +-- 2021-02-22: NOTE: `normalizeValue` should be adopted to work without flip, but currently was recieving infinite type. +normalForm_ t = void (flip forceEff `normalizeValue` t) stubCycles :: forall t f m diff --git a/src/Nix/Standard.hs b/src/Nix/Standard.hs index b512a6467..36598ab0b 100644 --- a/src/Nix/Standard.hs +++ b/src/Nix/Standard.hs @@ -129,8 +129,8 @@ instance ( MonadAtomicRef m thunk = fmap (StdThunk . StdCited) . thunk thunkId = thunkId . _stdCited . _stdThunk queryM x b f = queryM (_stdCited (_stdThunk x)) b f - force = force . _stdCited . _stdThunk - forceEff = forceEff . _stdCited . _stdThunk + force f t = force f (_stdCited $ _stdThunk t) + forceEff f t = forceEff f (_stdCited $ _stdThunk t) further = (fmap (StdThunk . StdCited) .) . further . _stdCited . _stdThunk instance ( MonadAtomicRef m @@ -151,7 +151,7 @@ instance ( MonadAtomicRef m -> m r ) -> m r - demand (Pure v) f = force v (flip demand f) + demand (Pure v) f = force (`demand` f) v demand (Free v) f = f (Free v) inform diff --git a/src/Nix/Thunk.hs b/src/Nix/Thunk.hs index 08e0c8f57..b9dfff507 100644 --- a/src/Nix/Thunk.hs +++ b/src/Nix/Thunk.hs @@ -49,8 +49,8 @@ class MonadThunkId m => MonadThunk t m a | t -> m, t -> a where thunkId :: t -> ThunkId m queryM :: t -> m r -> (a -> m r) -> m r - force :: t -> (a -> m r) -> m r - forceEff :: t -> (a -> m r) -> m r + force :: (a -> m r) -> t -> m r + forceEff :: (a -> m r) -> t -> m r -- | Modify the action to be performed by the thunk. For some implicits -- this modifies the thunk, for others it may create a new thunk. diff --git a/src/Nix/Thunk/Basic.hs b/src/Nix/Thunk/Basic.hs index 5e25b17b1..6e3d2f0f8 100644 --- a/src/Nix/Thunk/Basic.hs +++ b/src/Nix/Thunk/Basic.hs @@ -62,10 +62,10 @@ queryThunk (Thunk _ active ref) n k = do forceThunk :: forall m v a . (MonadVar m, MonadThrow m, MonadCatch m, Show (ThunkId m)) - => NThunkF m v - -> (v -> m a) + => (v -> m a) + -> NThunkF m v -> m a -forceThunk (Thunk n active ref) k = do +forceThunk k (Thunk n active ref) = do eres <- readVar ref case eres of Computed v -> k v @@ -81,8 +81,8 @@ forceThunk (Thunk n active ref) k = do writeVar ref (Computed v) k v -forceEffects :: MonadVar m => NThunkF m v -> (v -> m r) -> m r -forceEffects (Thunk _ active ref) k = do +forceEffects :: MonadVar m => (v -> m r) -> NThunkF m v -> m r +forceEffects k (Thunk _ active ref) = do nowActive <- atomicModifyVar active (True, ) if nowActive then pure $ error "Loop detected" diff --git a/src/Nix/Value.hs b/src/Nix/Value.hs index bdca6ac8e..a6f7bcdf4 100644 --- a/src/Nix/Value.hs +++ b/src/Nix/Value.hs @@ -662,7 +662,7 @@ describeValue = \case showValueType :: (MonadThunk t m (NValue t f m), Comonad f) => NValue t f m -> m String -showValueType (Pure t) = force t showValueType +showValueType (Pure t) = force showValueType t showValueType (Free (NValue (extract -> v))) = pure $ describeValue $ valueType v diff --git a/src/Nix/Value/Equal.hs b/src/Nix/Value/Equal.hs index 5c4e8dc16..e272b66ef 100644 --- a/src/Nix/Value/Equal.hs +++ b/src/Nix/Value/Equal.hs @@ -155,7 +155,7 @@ valueEqM x@(Free _) ( Pure y) = thunkEqM ?? y =<< thunk (pure x) valueEqM (Free (NValue (extract -> x))) (Free (NValue (extract -> y))) = valueFEqM (compareAttrSetsM f valueEqM) valueEqM x y where - f (Pure t) = force t $ \case + f (Pure t) = (`force` t) $ \case NVStr s -> pure $ pure s _ -> pure mempty f (Free v) = case v of @@ -163,7 +163,7 @@ valueEqM (Free (NValue (extract -> x))) (Free (NValue (extract -> y))) = _ -> pure mempty thunkEqM :: (MonadThunk t m (NValue t f m), Comonad f) => t -> t -> m Bool -thunkEqM lt rt = force lt $ \lv -> force rt $ \rv -> +thunkEqM lt rt = (`force` lt) $ \lv -> (`force` rt) $ \rv -> let unsafePtrEq = case (lt, rt) of (thunkId -> lid, thunkId -> rid) | lid == rid -> pure True _ -> valueEqM lv rv From 20d5f67536dfeba5b722d8366d9c4cee4bcecc8d Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Mon, 22 Feb 2021 21:44:43 +0200 Subject: [PATCH 03/14] Nix.Standard: add sigs to instance MonadThunk (StdThunk m) m (StdValue m) --- src/Nix/Standard.hs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Nix/Standard.hs b/src/Nix/Standard.hs index 36598ab0b..3822816a6 100644 --- a/src/Nix/Standard.hs +++ b/src/Nix/Standard.hs @@ -126,11 +126,22 @@ instance ( MonadAtomicRef m , MonadThunkId m ) => MonadThunk (StdThunk m) m (StdValue m) where - thunk = fmap (StdThunk . StdCited) . thunk + + thunk :: m (StdValue m) -> m (StdThunk m) + thunk = fmap (StdThunk . StdCited) . thunk + + thunkId :: StdThunk m -> ThunkId m thunkId = thunkId . _stdCited . _stdThunk + queryM x b f = queryM (_stdCited (_stdThunk x)) b f + + force :: (StdValue m -> m r) -> StdThunk m -> m r force f t = force f (_stdCited $ _stdThunk t) + + forceEff :: (StdValue m -> m r) -> StdThunk m -> m r forceEff f t = forceEff f (_stdCited $ _stdThunk t) + + further :: StdThunk m -> (m (StdValue m) -> m (StdValue m)) -> m (StdThunk m) further = (fmap (StdThunk . StdCited) .) . further . _stdCited . _stdThunk instance ( MonadAtomicRef m From eb97831a36eaad07c37295cfce1519fe4bb9bea6 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Mon, 22 Feb 2021 22:49:45 +0200 Subject: [PATCH 04/14] {Cited.Basic, Lint}: add instance sigs --- src/Nix/Cited/Basic.hs | 8 ++++++++ src/Nix/Lint.hs | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/src/Nix/Cited/Basic.hs b/src/Nix/Cited/Basic.hs index 84263eb48..4302c1d4c 100644 --- a/src/Nix/Cited/Basic.hs +++ b/src/Nix/Cited/Basic.hs @@ -8,6 +8,7 @@ {-# LANGUAGE TypeApplications #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE ViewPatterns #-} +{-# LANGUAGE InstanceSigs #-} module Nix.Cited.Basic where @@ -52,6 +53,8 @@ instance ( Has e Options , MonadCatch m ) => MonadThunk (Cited u f m t) m v where + + thunk :: m v -> m (Cited u f m t) thunk mv = do opts :: Options <- asks (view hasLens) @@ -72,14 +75,17 @@ instance ( Has e Options fmap (Cited . NCited ps) . thunk $ mv else fmap (Cited . NCited mempty) . thunk $ mv + thunkId :: Cited u f m t -> ThunkId m thunkId (Cited (NCited _ t)) = thunkId @_ @m t + queryM :: Cited u f m t -> m r -> (v -> m r) -> m r queryM (Cited (NCited _ t)) = queryM t -- | The ThunkLoop exception is thrown as an exception with MonadThrow, -- which does not capture the current stack frame information to provide -- it in a NixException, so we catch and re-throw it here using -- 'throwError' from Frames.hs. + force :: (v -> m r) -> Cited u f m t -> m r force f (Cited (NCited ps t)) = catch go (throwError @ThunkLoop) where @@ -88,6 +94,7 @@ instance ( Has e Options Provenance scope e@(Compose (Ann s _)) : _ -> withFrame Info (ForcingExpr scope (wrapExprLoc s e)) (force f t) + forceEff :: (v -> m r) -> Cited u f m t -> m r forceEff f (Cited (NCited ps t)) = catch go (throwError @ThunkLoop) @@ -97,4 +104,5 @@ instance ( Has e Options Provenance scope e@(Compose (Ann s _)) : _ -> withFrame Info (ForcingExpr scope (wrapExprLoc s e)) (forceEff f t) + further :: Cited u f m t -> (m v -> m v) -> m (Cited u f m t) further (Cited (NCited ps t)) f = Cited . NCited ps <$> further t f diff --git a/src/Nix/Lint.hs b/src/Nix/Lint.hs index 470d0a06f..13e5015d5 100644 --- a/src/Nix/Lint.hs +++ b/src/Nix/Lint.hs @@ -12,6 +12,7 @@ {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE InstanceSigs #-} {-# OPTIONS_GHC -fno-warn-name-shadowing #-} {-# OPTIONS_GHC -Wno-missing-methods #-} @@ -265,7 +266,11 @@ instance ToValue (AttrSet (Symbolic m), AttrSet SourcePos) m (Symbolic m) where instance (MonadThunkId m, MonadAtomicRef m, MonadCatch m) => MonadValue (Symbolic m) m where + + defer :: m (Symbolic m) -> m (Symbolic m) defer = fmap ST . thunk + + demand :: Symbolic m -> (Symbolic m -> m r) -> m r demand (ST v) f = force (`demand` f) v demand (SV v) f = f (SV v) From 9bc2bbc929aeb6fd3581cd36a230951c6c428d69 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Tue, 23 Feb 2021 16:00:09 +0200 Subject: [PATCH 05/14] Value.Equal: valueEQ: rm RankNTypes forall --- src/Nix/Value/Equal.hs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Nix/Value/Equal.hs b/src/Nix/Value/Equal.hs index e272b66ef..6213d17c6 100644 --- a/src/Nix/Value/Equal.hs +++ b/src/Nix/Value/Equal.hs @@ -97,8 +97,7 @@ valueFEqM attrsEq eq = curry $ \case (NVConstantF (NFloat x), NVConstantF (NInt y) ) -> pure $ x == fromInteger y (NVConstantF (NInt x), NVConstantF (NFloat y)) -> pure $ fromInteger x == y (NVConstantF lc , NVConstantF rc ) -> pure $ lc == rc - (NVStrF ls, NVStrF rs) -> - pure $ stringIgnoreContext ls == stringIgnoreContext rs + (NVStrF ls, NVStrF rs) -> pure $ (\i -> i ls == i rs) stringIgnoreContext (NVListF ls , NVListF rs ) -> alignEqM eq ls rs (NVSetF lm _, NVSetF rm _) -> attrsEq lm rm (NVPathF lp , NVPathF rp ) -> pure $ lp == rp @@ -144,8 +143,7 @@ compareAttrSets f eq lm rm = runIdentity $ compareAttrSetsM (Identity . f) (\x y -> Identity (eq x y)) lm rm valueEqM - :: forall t f m - . (MonadThunk t m (NValue t f m), Comonad f) + :: (MonadThunk t m (NValue t f m), Comonad f) => NValue t f m -> NValue t f m -> m Bool From 41d0062237b6c8ae2716b6ffdf8095bb4bd1c6f4 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Tue, 23 Feb 2021 16:02:33 +0200 Subject: [PATCH 06/14] Value.Equal: clean-up language extentions --- src/Nix/Standard.hs | 2 +- src/Nix/Value/Equal.hs | 11 ----------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/src/Nix/Standard.hs b/src/Nix/Standard.hs index 3822816a6..56ea22f79 100644 --- a/src/Nix/Standard.hs +++ b/src/Nix/Standard.hs @@ -172,7 +172,7 @@ instance ( MonadAtomicRef m ) -> m (StdValue m) inform (Pure t) f = Pure <$> further t f - inform (Free v) f = Free <$> bindNValue' id (flip inform f) v + inform (Free v) f = Free <$> bindNValue' id (`inform` f) v {------------------------------------------------------------------------} diff --git a/src/Nix/Value/Equal.hs b/src/Nix/Value/Equal.hs index 6213d17c6..f7e4bb430 100644 --- a/src/Nix/Value/Equal.hs +++ b/src/Nix/Value/Equal.hs @@ -1,23 +1,12 @@ {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE ConstraintKinds #-} -{-# LANGUAGE DataKinds #-} -{-# LANGUAGE DeriveAnyClass #-} -{-# LANGUAGE DeriveDataTypeable #-} -{-# LANGUAGE DeriveGeneric #-} -{-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PatternSynonyms #-} -{-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE StandaloneDeriving #-} -{-# LANGUAGE TemplateHaskell #-} -{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} -{-# LANGUAGE TypeOperators #-} {-# LANGUAGE ViewPatterns #-} {-# OPTIONS_GHC -Wno-missing-pattern-synonym-signatures #-} From afd88b79ed60ea7a2a7edc1f1d88f3899cae6f20 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Tue, 23 Feb 2021 17:34:34 +0200 Subject: [PATCH 07/14] ChangeLog: add info on the `force{,Eff}` changes --- ChangeLog.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index 750c2c2ea..91d904b23 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -5,6 +5,11 @@ * Breaking: + * [(link)](https://github.com/haskell-nix/hnix/pull/859/files#diff-ed4fba9b7db93932de22f4ef09d04b07a2ba88888e42207eb9abe6ff10b7ca2b) `Nix.Thunk`: `class MonadThunk t m a | t -> m, t -> a` : `force{,Eff}` unflipped the arguments. All their implementations tail recurse. + * If some of the `force`, `forceEff`, `forceThunk`, `forceEffects` are used - simply flip the arguments for them. + + * [(link)](https://github.com/haskell-nix/hnix/pull/859/commits/8e043bcbda13ea4fd66d3eefd6da690bb3923edd) `Nix.Value.Equal`: `valueEqM`: freed from `RankNTypes: forall t f m .`. + * [(link)](https://github.com/haskell-nix/hnix/pull/802/commits/529095deaf6bc6b102fe5a3ac7baccfbb8852e49#) `Nix.Strings`: all `hacky*` functions replaced with lawful implemetations, because of that all functions become lawful - dropped the `principled` suffix from functions: * `Nix.String`: ```haskell From efde45cd05c5fe458689616f63189afd97275972 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Tue, 23 Feb 2021 17:56:17 +0200 Subject: [PATCH 08/14] Thunk.Basic: m cosmetic --- src/Nix/Thunk/Basic.hs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Nix/Thunk/Basic.hs b/src/Nix/Thunk/Basic.hs index 6e3d2f0f8..97fbdafa4 100644 --- a/src/Nix/Thunk/Basic.hs +++ b/src/Nix/Thunk/Basic.hs @@ -46,7 +46,11 @@ buildThunk action = do freshThunkId <- freshId Thunk freshThunkId <$> newVar False <*> newVar (Deferred action) -queryThunk :: MonadVar m => NThunkF m v -> m a -> (v -> m a) -> m a +queryThunk :: MonadVar m + => NThunkF m v + -> m a + -> (v -> m a) + -> m a queryThunk (Thunk _ active ref) n k = do nowActive <- atomicModifyVar active (True, ) if nowActive @@ -81,7 +85,10 @@ forceThunk k (Thunk n active ref) = do writeVar ref (Computed v) k v -forceEffects :: MonadVar m => (v -> m r) -> NThunkF m v -> m r +forceEffects :: MonadVar m + => (v -> m r) + -> NThunkF m v + -> m r forceEffects k (Thunk _ active ref) = do nowActive <- atomicModifyVar active (True, ) if nowActive @@ -96,7 +103,10 @@ forceEffects k (Thunk _ active ref) = do _ <- atomicModifyVar active (False, ) k v -furtherThunk :: MonadVar m => NThunkF m v -> (m v -> m v) -> m (NThunkF m v) +furtherThunk :: MonadVar m + => NThunkF m v + -> (m v -> m v) + -> m (NThunkF m v) furtherThunk t@(Thunk _ _ ref) k = do _ <- atomicModifyVar ref $ \x -> case x of Computed _ -> (x, x) From a32319dda647b8909ba9ae79db0f46edf35b2ce8 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Tue, 23 Feb 2021 18:30:08 +0200 Subject: [PATCH 09/14] Nix.Standard: add instance sign to `queryM` --- src/Nix/Standard.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Nix/Standard.hs b/src/Nix/Standard.hs index 56ea22f79..5f6be3718 100644 --- a/src/Nix/Standard.hs +++ b/src/Nix/Standard.hs @@ -133,6 +133,7 @@ instance ( MonadAtomicRef m thunkId :: StdThunk m -> ThunkId m thunkId = thunkId . _stdCited . _stdThunk + queryM :: StdThunk m -> m r -> (StdValue m -> m r) -> m r queryM x b f = queryM (_stdCited (_stdThunk x)) b f force :: (StdValue m -> m r) -> StdThunk m -> m r @@ -142,7 +143,7 @@ instance ( MonadAtomicRef m forceEff f t = forceEff f (_stdCited $ _stdThunk t) further :: StdThunk m -> (m (StdValue m) -> m (StdValue m)) -> m (StdThunk m) - further = (fmap (StdThunk . StdCited) .) . further . _stdCited . _stdThunk + further t f = ((fmap (StdThunk . StdCited) .) $ further $ _stdCited $ _stdThunk t) f instance ( MonadAtomicRef m , MonadCatch m From fcceddf525aece1823ae957a37b12544d23b6d4b Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Tue, 23 Feb 2021 19:33:38 +0200 Subject: [PATCH 10/14] Thunk: unflip the `further` instances `forces` are already flipped, which gives tail recursion. This one gives more straight-forward implementation & use, maybe with some performance optimization. M src/Nix/Cited/Basic.hs M src/Nix/Standard.hs M src/Nix/Thunk.hs M src/Nix/Thunk/Basic.hs --- src/Nix/Cited/Basic.hs | 4 ++-- src/Nix/Standard.hs | 8 ++++---- src/Nix/Thunk.hs | 2 +- src/Nix/Thunk/Basic.hs | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Nix/Cited/Basic.hs b/src/Nix/Cited/Basic.hs index 4302c1d4c..529ac2e36 100644 --- a/src/Nix/Cited/Basic.hs +++ b/src/Nix/Cited/Basic.hs @@ -104,5 +104,5 @@ instance ( Has e Options Provenance scope e@(Compose (Ann s _)) : _ -> withFrame Info (ForcingExpr scope (wrapExprLoc s e)) (forceEff f t) - further :: Cited u f m t -> (m v -> m v) -> m (Cited u f m t) - further (Cited (NCited ps t)) f = Cited . NCited ps <$> further t f + further :: (m v -> m v) -> Cited u f m t -> m (Cited u f m t) + further f (Cited (NCited ps t)) = Cited . NCited ps <$> further f t diff --git a/src/Nix/Standard.hs b/src/Nix/Standard.hs index 5f6be3718..6aa426cb1 100644 --- a/src/Nix/Standard.hs +++ b/src/Nix/Standard.hs @@ -128,7 +128,7 @@ instance ( MonadAtomicRef m => MonadThunk (StdThunk m) m (StdValue m) where thunk :: m (StdValue m) -> m (StdThunk m) - thunk = fmap (StdThunk . StdCited) . thunk + thunk v = StdThunk . StdCited <$> thunk v thunkId :: StdThunk m -> ThunkId m thunkId = thunkId . _stdCited . _stdThunk @@ -142,8 +142,8 @@ instance ( MonadAtomicRef m forceEff :: (StdValue m -> m r) -> StdThunk m -> m r forceEff f t = forceEff f (_stdCited $ _stdThunk t) - further :: StdThunk m -> (m (StdValue m) -> m (StdValue m)) -> m (StdThunk m) - further t f = ((fmap (StdThunk . StdCited) .) $ further $ _stdCited $ _stdThunk t) f + further :: (m (StdValue m) -> m (StdValue m)) -> StdThunk m -> m (StdThunk m) + further f t = StdThunk . StdCited <$> further f (_stdCited $ _stdThunk t) instance ( MonadAtomicRef m , MonadCatch m @@ -172,7 +172,7 @@ instance ( MonadAtomicRef m -> m (StdValue m) ) -> m (StdValue m) - inform (Pure t) f = Pure <$> further t f + inform (Pure t) f = Pure <$> further f t inform (Free v) f = Free <$> bindNValue' id (`inform` f) v {------------------------------------------------------------------------} diff --git a/src/Nix/Thunk.hs b/src/Nix/Thunk.hs index b9dfff507..a693e42e1 100644 --- a/src/Nix/Thunk.hs +++ b/src/Nix/Thunk.hs @@ -54,7 +54,7 @@ class MonadThunkId m => MonadThunk t m a | t -> m, t -> a where -- | Modify the action to be performed by the thunk. For some implicits -- this modifies the thunk, for others it may create a new thunk. - further :: t -> (m a -> m a) -> m t + further :: (m a -> m a) -> t -> m t newtype ThunkLoop = ThunkLoop String -- contains rendering of ThunkId deriving Typeable diff --git a/src/Nix/Thunk/Basic.hs b/src/Nix/Thunk/Basic.hs index 97fbdafa4..8ff388cf2 100644 --- a/src/Nix/Thunk/Basic.hs +++ b/src/Nix/Thunk/Basic.hs @@ -104,10 +104,10 @@ forceEffects k (Thunk _ active ref) = do k v furtherThunk :: MonadVar m - => NThunkF m v - -> (m v -> m v) + => (m v -> m v) + -> NThunkF m v -> m (NThunkF m v) -furtherThunk t@(Thunk _ _ ref) k = do +furtherThunk k t@(Thunk _ _ ref) = do _ <- atomicModifyVar ref $ \x -> case x of Computed _ -> (x, x) Deferred d -> (Deferred (k d), x) From 46c9ab8df95b5da9bcff23225ce11445a59c7806 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Tue, 23 Feb 2021 19:42:23 +0200 Subject: [PATCH 11/14] ChangeLog: add `further{,Thunk}` information --- ChangeLog.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 91d904b23..7da5abecb 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -5,8 +5,14 @@ * Breaking: - * [(link)](https://github.com/haskell-nix/hnix/pull/859/files#diff-ed4fba9b7db93932de22f4ef09d04b07a2ba88888e42207eb9abe6ff10b7ca2b) `Nix.Thunk`: `class MonadThunk t m a | t -> m, t -> a` : `force{,Eff}` unflipped the arguments. All their implementations tail recurse. - * If some of the `force`, `forceEff`, `forceThunk`, `forceEffects` are used - simply flip the arguments for them. + * [(link)](https://github.com/haskell-nix/hnix/pull/859/files#diff-ed4fba9b7db93932de22f4ef09d04b07a2ba88888e42207eb9abe6ff10b7ca2b) `Nix.Thunk`: `class MonadThunk t m a | t -> m, t -> a` : `force{,Eff}` unflipped the arguments. All their implementations got more straigh-forward to use and `force*`s now tail recurse. + * Simply flip the first two arguments for: + * `force` + * `forceEff` + * `forceThunk` + * `forceEffects` + * `further` + * `furtherThunk` * [(link)](https://github.com/haskell-nix/hnix/pull/859/commits/8e043bcbda13ea4fd66d3eefd6da690bb3923edd) `Nix.Value.Equal`: `valueEqM`: freed from `RankNTypes: forall t f m .`. From b128317bcd6277b49d2cf61c0608fcd37c219e90 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Thu, 25 Feb 2021 16:11:26 +0200 Subject: [PATCH 12/14] treewide: proper order of `querry{M,Thunk}` arguments They are not really used currently in the project. This commit concludes the `class MonadThunk` arguments optimization work. Next would be unflip of the `demand` and the moving-out of the stuff from the implementations. ChangeLog: add note on the querry{M,Thunk} changes --- ChangeLog.md | 3 +++ src/Nix/Cited/Basic.hs | 4 ++-- src/Nix/Normal.hs | 5 +++-- src/Nix/Standard.hs | 4 ++-- src/Nix/Thunk.hs | 10 +++++----- src/Nix/Thunk/Basic.hs | 30 ++++++++++++++++++++---------- src/Nix/Type/Infer.hs | 6 +++--- src/Nix/Var.hs | 5 +++-- 8 files changed, 41 insertions(+), 26 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 7da5abecb..9eb4d8024 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -13,6 +13,9 @@ * `forceEffects` * `further` * `furtherThunk` + * Simply switch the 1<->3 arguments in: + * `querryM` + * `querryThunk` * [(link)](https://github.com/haskell-nix/hnix/pull/859/commits/8e043bcbda13ea4fd66d3eefd6da690bb3923edd) `Nix.Value.Equal`: `valueEqM`: freed from `RankNTypes: forall t f m .`. diff --git a/src/Nix/Cited/Basic.hs b/src/Nix/Cited/Basic.hs index 529ac2e36..d330a67e9 100644 --- a/src/Nix/Cited/Basic.hs +++ b/src/Nix/Cited/Basic.hs @@ -78,8 +78,8 @@ instance ( Has e Options thunkId :: Cited u f m t -> ThunkId m thunkId (Cited (NCited _ t)) = thunkId @_ @m t - queryM :: Cited u f m t -> m r -> (v -> m r) -> m r - queryM (Cited (NCited _ t)) = queryM t + queryM :: (v -> m r) -> m r -> Cited u f m t -> m r + queryM f m (Cited (NCited _ t)) = queryM f m t -- | The ThunkLoop exception is thrown as an exception with MonadThrow, -- which does not capture the current stack frame information to provide diff --git a/src/Nix/Normal.hs b/src/Nix/Normal.hs index d767664b4..0baafeaa0 100644 --- a/src/Nix/Normal.hs +++ b/src/Nix/Normal.hs @@ -122,7 +122,8 @@ removeEffects removeEffects = iterNValueM id - (`queryM` pure opaque) + -- 2021-02-25: NOTE: Please, unflip this up the stack + (\ t f -> queryM f (pure opaque) t) (fmap Free . sequenceNValue' id) opaque :: Applicative f => NValue t f m @@ -132,4 +133,4 @@ dethunk :: (MonadThunk t m (NValue t f m), MonadDataContext f m) => t -> m (NValue t f m) -dethunk t = queryM t (pure opaque) removeEffects +dethunk t = queryM removeEffects (pure opaque) t diff --git a/src/Nix/Standard.hs b/src/Nix/Standard.hs index 6aa426cb1..693a8173d 100644 --- a/src/Nix/Standard.hs +++ b/src/Nix/Standard.hs @@ -133,8 +133,8 @@ instance ( MonadAtomicRef m thunkId :: StdThunk m -> ThunkId m thunkId = thunkId . _stdCited . _stdThunk - queryM :: StdThunk m -> m r -> (StdValue m -> m r) -> m r - queryM x b f = queryM (_stdCited (_stdThunk x)) b f + queryM :: (StdValue m -> m r) -> m r -> StdThunk m -> m r + queryM f b x = queryM f b (_stdCited (_stdThunk x)) force :: (StdValue m -> m r) -> StdThunk m -> m r force f t = force f (_stdCited $ _stdThunk t) diff --git a/src/Nix/Thunk.hs b/src/Nix/Thunk.hs index a693e42e1..d41d0bf3b 100644 --- a/src/Nix/Thunk.hs +++ b/src/Nix/Thunk.hs @@ -41,20 +41,20 @@ instance MonadThunkId m => MonadThunkId (StateT s m) where type ThunkId (StateT s m) = ThunkId m class MonadThunkId m => MonadThunk t m a | t -> m, t -> a where - thunk :: m a -> m t + thunk :: m a -> m t -- | Return an identifier for the thunk unless it is a pure value (i.e., -- strictly an encapsulation of some 'a' without any additional -- structure). For pure values represented as thunks, returns mempty. - thunkId :: t -> ThunkId m + thunkId :: t -> ThunkId m - queryM :: t -> m r -> (a -> m r) -> m r - force :: (a -> m r) -> t -> m r + queryM :: (a -> m r) -> m r -> t -> m r + force :: (a -> m r) -> t -> m r forceEff :: (a -> m r) -> t -> m r -- | Modify the action to be performed by the thunk. For some implicits -- this modifies the thunk, for others it may create a new thunk. - further :: (m a -> m a) -> t -> m t + further :: (m a -> m a) -> t -> m t newtype ThunkLoop = ThunkLoop String -- contains rendering of ThunkId deriving Typeable diff --git a/src/Nix/Thunk/Basic.hs b/src/Nix/Thunk/Basic.hs index 8ff388cf2..e39b5c6a3 100644 --- a/src/Nix/Thunk/Basic.hs +++ b/src/Nix/Thunk/Basic.hs @@ -16,6 +16,7 @@ import Control.Monad.Catch import Nix.Thunk import Nix.Var +import Data.Bool (bool) data Deferred m v = Deferred (m v) | Computed v deriving (Functor, Foldable, Traversable) @@ -46,20 +47,29 @@ buildThunk action = do freshThunkId <- freshId Thunk freshThunkId <$> newVar False <*> newVar (Deferred action) +-- 2021-02-25: NOTE: Please, look into thread handling of this. +-- Locking system was not implemented at the time. +-- How query operates? Is it normal that query on request if the thunk is locked - returns the thunk +-- and when the value calculation is deferred - returns the thunk, it smells fishy. +-- And because the query's impemetation are not used, only API - they pretty much could survive being that fishy. queryThunk :: MonadVar m - => NThunkF m v + => (v -> m a) -> m a - -> (v -> m a) + -> NThunkF m v -> m a -queryThunk (Thunk _ active ref) n k = do - nowActive <- atomicModifyVar active (True, ) - if nowActive - then n - else do +queryThunk k n (Thunk _ active ref) = do + thunkIsAvaliable <- not <$> atomicModifyVar active (True, ) + bool + n + go + thunkIsAvaliable + where + go = do eres <- readVar ref - res <- case eres of - Computed v -> k v - _ -> n + res <- + case eres of + Computed v -> k v + Deferred _mv -> n _ <- atomicModifyVar active (False, ) pure res diff --git a/src/Nix/Type/Infer.hs b/src/Nix/Type/Infer.hs index 3ad916741..b6bc3caf0 100644 --- a/src/Nix/Type/Infer.hs +++ b/src/Nix/Type/Infer.hs @@ -427,15 +427,15 @@ instance MonadInfer m thunk = fmap JThunk . thunk thunkId (JThunk x) = thunkId x - queryM (JThunk x) b f = queryM x b f + queryM f b (JThunk x) = queryM f b x -- If we have a thunk loop, we just don't know the type. - force (JThunk t) f = catch (force t f) + force f (JThunk t) = catch (force t f) $ \(_ :: ThunkLoop) -> f =<< Judgment As.empty mempty <$> fresh -- If we have a thunk loop, we just don't know the type. - forceEff (JThunk t) f = catch (forceEff t f) + forceEff f (JThunk t) = catch (forceEff f t) $ \(_ :: ThunkLoop) -> f =<< Judgment As.empty mempty <$> fresh -} diff --git a/src/Nix/Var.hs b/src/Nix/Var.hs index f4e67e116..b9c5ca502 100644 --- a/src/Nix/Var.hs +++ b/src/Nix/Var.hs @@ -38,16 +38,17 @@ atomicModifyVar :: MonadAtomicRef m => Ref m a -> (a -> (a, b)) -> m b atomicModifyVar = atomicModifyRef --TODO: Upstream GEq instances +-- 2021-02-25: NOTE: Currently, upstreaming would require adding a dependency on the according packages. instance GEq IORef where a `geq` b = bool Nothing (pure $ unsafeCoerce Refl) - (a == unsafeCoerce b ) + (a == unsafeCoerce b) instance GEq (STRef s) where a `geq` b = bool Nothing - (pure $ unsafeCoerce Refl ) + (pure $ unsafeCoerce Refl) (a == unsafeCoerce b) From 78d462b2c5d7d5ccf4884e30c839c3968328cae1 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Thu, 25 Feb 2021 16:26:03 +0200 Subject: [PATCH 13/14] Normal: unflip the `force*` passed to normalizeValue --- src/Nix/Normal.hs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Nix/Normal.hs b/src/Nix/Normal.hs index 0baafeaa0..26b4a9674 100644 --- a/src/Nix/Normal.hs +++ b/src/Nix/Normal.hs @@ -40,7 +40,7 @@ normalizeValue , MonadDataErrorContext t f m , Ord (ThunkId m) ) - => (forall r . t -> (NValue t f m -> m r) -> m r) + => (forall r . (NValue t f m -> m r) -> t -> m r) -> NValue t f m -> m (NValue t f m) normalizeValue f tnk = run $ iterNValueM run go (fmap Free . sequenceNValue' run) tnk @@ -65,7 +65,8 @@ normalizeValue f tnk = run $ iterNValueM run go (fmap Free . sequenceNValue' run i <- ask when (i > 2000) $ error "Exceeded maximum normalization depth of 2000 levels" - lifted (lifted (f t)) $ local succ . k + -- 2021-02-22: NOTE: `normalizeValue` should be adopted to work without fliping of the force (f) + lifted (lifted (`f` t)) $ local succ . k seen t = do let tid = thunkId t @@ -84,8 +85,7 @@ normalForm ) => NValue t f m -> m (NValue t f m) --- 2021-02-22: NOTE: `normalizeValue` should be adopted to work without flip, but currently was recieving infinite type. -normalForm t = stubCycles <$> (flip force `normalizeValue` t) +normalForm t = stubCycles <$> (force `normalizeValue` t) normalForm_ :: ( Framed e m @@ -95,8 +95,7 @@ normalForm_ ) => NValue t f m -> m () --- 2021-02-22: NOTE: `normalizeValue` should be adopted to work without flip, but currently was recieving infinite type. -normalForm_ t = void (flip forceEff `normalizeValue` t) +normalForm_ t = void (forceEff `normalizeValue` t) stubCycles :: forall t f m From 348c6ef8fcb6691e794afc5902a20136b9b67dc2 Mon Sep 17 00:00:00 2001 From: Anton-Latukha Date: Thu, 25 Feb 2021 18:01:35 +0200 Subject: [PATCH 14/14] (Pure -> pure) --- src/Nix/Normal.hs | 2 +- src/Nix/Standard.hs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nix/Normal.hs b/src/Nix/Normal.hs index 26b4a9674..85cbb064f 100644 --- a/src/Nix/Normal.hs +++ b/src/Nix/Normal.hs @@ -60,7 +60,7 @@ normalizeValue f tnk = run $ iterNValueM run go (fmap Free . sequenceNValue' run go t k = do b <- seen t if b - then pure $ Pure t + then pure $ pure t else do i <- ask when (i > 2000) diff --git a/src/Nix/Standard.hs b/src/Nix/Standard.hs index 693a8173d..b8f8e05a5 100644 --- a/src/Nix/Standard.hs +++ b/src/Nix/Standard.hs @@ -155,7 +155,7 @@ instance ( MonadAtomicRef m defer :: m (StdValue m) -> m (StdValue m) - defer = fmap Pure . thunk + defer = fmap pure . thunk demand :: StdValue m