diff options
-rw-r--r-- | docs/users_guide/exts/implicit_parameters.rst | 23 | ||||
-rw-r--r-- | testsuite/tests/simplCore/should_run/T23289.hs | 13 | ||||
-rw-r--r-- | testsuite/tests/simplCore/should_run/T23289.stdout | 2 | ||||
-rw-r--r-- | testsuite/tests/simplCore/should_run/all.T | 1 |
4 files changed, 37 insertions, 2 deletions
diff --git a/docs/users_guide/exts/implicit_parameters.rst b/docs/users_guide/exts/implicit_parameters.rst index a8da87e416..ee6234e55a 100644 --- a/docs/users_guide/exts/implicit_parameters.rst +++ b/docs/users_guide/exts/implicit_parameters.rst @@ -180,6 +180,27 @@ parameter. So we get the following results in GHCi: Adding a type signature dramatically changes the result! This is a rather counter-intuitive phenomenon, worth watching out for. +Implicit parameters scoping guarantees +------------------------------------- + +GHC always takes the most nested implicit parameter binding from the +context to find the value. Consider the following code:: + + let ?f = 1 in let ?f = 2 in ?f + +This expression will always return 2. + +Another example of this rule is matching over constructors with constraints. +For example:: + + data T where + MkT :: (?f :: Int) => T + + f :: T -> T -> Int + f MkT MkT = ?f + +Here GHC will always take ``?f`` from the last match. + Implicit parameters and monomorphism ------------------------------------ @@ -199,5 +220,3 @@ a type signature for ``y``, then ``y`` will get type ``(?x::Int) => Int``, so the occurrence of ``y`` in the body of the ``let`` will see the inner binding of ``?x``, so ``(f 9)`` will return ``14``. - - diff --git a/testsuite/tests/simplCore/should_run/T23289.hs b/testsuite/tests/simplCore/should_run/T23289.hs new file mode 100644 index 0000000000..38e32ae279 --- /dev/null +++ b/testsuite/tests/simplCore/should_run/T23289.hs @@ -0,0 +1,13 @@ +{-# LANGUAGE ImplicitParams, GADTs #-} +module Main where + +data T where + MkT :: (?f :: Int) => T + +f :: T -> T -> Int +f MkT MkT = ?f + +main :: IO () +main = do + print (let ?g = 1 in let ?g = 2 in ?g) + print $ f (let ?f = 3 in MkT) (let ?f = 4 in MkT) diff --git a/testsuite/tests/simplCore/should_run/T23289.stdout b/testsuite/tests/simplCore/should_run/T23289.stdout new file mode 100644 index 0000000000..da7f84740b --- /dev/null +++ b/testsuite/tests/simplCore/should_run/T23289.stdout @@ -0,0 +1,2 @@ +2 +4 diff --git a/testsuite/tests/simplCore/should_run/all.T b/testsuite/tests/simplCore/should_run/all.T index bb23475071..7348e1015a 100644 --- a/testsuite/tests/simplCore/should_run/all.T +++ b/testsuite/tests/simplCore/should_run/all.T @@ -111,3 +111,4 @@ test('T22448', normal, compile_and_run, ['-O1']) test('T22998', normal, compile_and_run, ['-O0 -fspecialise -dcore-lint']) test('T23184', normal, compile_and_run, ['-O']) test('T23134', normal, compile_and_run, ['-O0 -fcatch-nonexhaustive-cases']) +test('T23289', normal, compile_and_run, ['']) |