#7398: RULES don't apply to a newtype constructor
-------------------------------------+-------------------------------------
Reporter: shachaf | Owner: (none)
Type: bug | Status: new
Priority: normal | Milestone: 8.6.1
Component: Compiler | Version: 7.6.1
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
Type of failure: Runtime | Unknown/Multiple
performance bug | Test Case:
Blocked By: | Blocking:
Related Tickets: #6082, #10418, | Differential Rev(s):
#13290 |
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by nomeata):
> The alternative is to try to make the rule work after inlining MkT, by
being clever about casts. That might be possible.
We somewhat do this already: We have
{{{
{-# RULES "map/coerce" [1] map coerce = coerce #-}
}}}
which fires in all these cases:
{{{
foo :: [Int] -> [Int]
foo = map id
fooAge :: [Int] -> [Age]
fooAge = map Age
fooCoerce :: [Int] -> [Age]
fooCoerce = map coerce
fooUnsafeCoerce :: [Int] -> [Age]
fooUnsafeCoerce = map unsafeCoerce
}}}
(this is `testsuite/tests/simplCore/should_run/T2110.hs`).
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/7398#comment:16>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
#7398: RULES don't apply to a newtype constructor
-------------------------------------+-------------------------------------
Reporter: shachaf | Owner: (none)
Type: bug | Status: new
Priority: normal | Milestone: 8.6.1
Component: Compiler | Version: 7.6.1
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
Type of failure: Runtime | Unknown/Multiple
performance bug | Test Case:
Blocked By: | Blocking:
Related Tickets: #6082, #10418, | Differential Rev(s):
#13290 |
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by simonpj):
Currently, wen you have
{{{
{-# RULES "foo" forall x. f (g x) = h x #-}
}}}
we have to delay inlining `g` until the rule has had a decent
chance to fire. We currently do this manually, usually thus
{{{
{-# NOINLINE[1] f,g #-}
}}}
The obvious thing for newtypes (and indeed other data constructors, if
they have wrappers that unpack their arguments) is to delay inlining them.
Something like
{{{
newtype T a = MkT (Maybe a)
{-# NOINLINE[1] MkT #-}
}}}
We don't support that right now, but we could.
The alternative is to try to make the rule work ''after'' inlining `MkT`,
by being clever about casts. That might be possible.
But it doesn't work for data constructors like
{{{
data S = MkS {-# UNPACK #-} !Int
}}}
where the wrapper evaluates and unboxes the argument. After inlining, the
original `(f (MkS x))` turns into `f (case x ov I# y -> MkS y)`, which is
a lot harder to match.
So I think my suggestion, for now, is that we might want to allow users to
put a NOINLINE pragma on data constructors.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/7398#comment:15>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
#7398: RULES don't apply to a newtype constructor
-------------------------------------+-------------------------------------
Reporter: shachaf | Owner: (none)
Type: bug | Status: new
Priority: normal | Milestone: 8.6.1
Component: Compiler | Version: 7.6.1
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
Type of failure: Runtime | Unknown/Multiple
performance bug | Test Case:
Blocked By: | Blocking:
Related Tickets: #6082, #10418, | Differential Rev(s):
#13290 |
Wiki Page: |
-------------------------------------+-------------------------------------
Changes (by dfeuer):
* milestone: => 8.6.1
Comment:
I'm adding a milestone because I suspect we may have enough machinery to
make this work . Consider this code:
{{{#!hs
import Data.Functor.Identity
import Data.Coerce
hello :: (a -> b) -> a -> b
hello f x = f x
{-# INLINE [1] hello #-}
{-# RULES
"not good" forall (f :: Identity a -> a) x. hello f (Identity x) = x
"also bad" forall f (x :: a). hello f (Identity x :: Identity a) = x
"yes good" forall (f :: Identity a -> a) x. hello f (coerce x) = x
"also good" forall f (x :: a) . hello f (coerce x :: Identity a) = x
"just fine" forall f (x :: a). hello f (coerce @a @(Identity a) x) = x
#-}
test :: (Identity a -> a) -> a -> a
test f x = hello f (Identity x)
{-# NOINLINE test #-}
}}}
The rule labeled "not good" doesn't fire, but the one labeled "yes good"
fires. The only difference is the spelling of `coerce`! This seems to
suggest that we can apply some of the machinery for `coerce` rules to
sometimes make good things happen. In particular, it seems likely that
after type checking the rule, we can simply replace each `newtype`
constructor/accessor with an appropriately typed invocation of `coerce`,
and make the rules engine work.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/7398#comment:13>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
#2893: Implement "Quantified contexts" proposal
-------------------------------------+-------------------------------------
Reporter: porges | Owner: (none)
Type: feature request | Status: new
Priority: normal | Milestone: ⊥
Component: Compiler | Version: 6.10.1
Resolution: | Keywords:
| QuantifiedContexts
Operating System: Unknown/Multiple | Architecture:
| Unknown/Multiple
Type of failure: None/Unknown | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s):
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by simonpj):
I've build an implementation of `QuantifiedConstraints`, held on
`wip/T2893`. Here's the commit message
{{{
commit dbcf8d0b9076ae32b9138623eb84f67c18ed3dab
Author: Simon Peyton Jones <simonpj(a)microsoft.com>
Date: Sat Jan 27 14:32:34 2018 +0000
Implement QuantifiedConstraints
We have wanted quantified constraints for ages and, as I hoped,
they proved remarkably simple to implement. All the machinery was
already in place.
The main ticket is Trac #2893, but also relevant are
#5927
#8516
#9123 (especially! higher kinded roles)
#14070
#14317
The wiki page is
https://ghc.haskell.org/trac/ghc/wiki/QuantifiedContexts
Here is the relevant Note:
Note [Quantified constraints]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The -XQuantifiedConstraints extension allows type-class contexts like
this:
data Rose f x = Rose x (f (Rose f x))
instance (Eq a, forall b. Eq b => Eq (f b))
=> Eq (Rose f a) where
(Rose x1 rs1) == (Rose x2 rs2) = x1==x2 && rs1 >= rs2
Note the (forall b. Eq b => Eq (f b)) in the instance contexts.
This quantified constraint is needed to solve the
[W] (Eq (f (Rose f x)))
constraint which arises form the (==) definition.
Here are the moving parts
* Language extension {-# LANGUAGE QuantifiedConstraints #-}
and add it to ghc-boot-th:GHC.LanguageExtensions.Type.Extension
* A new form of evidence, EvDFun, that is used to discharge
such wanted constraints
* checkValidType gets some changes to accept forall-constraints
only in the right places.
* Type.PredTree gets a new constructor ForAllPred, and
and classifyPredType analyses a PredType to decompose
the new forall-constraints
* TcSMonad.InertCans gets an extra field, inert_insts,
which holds all the Given forall-constraints. In effect,
such Given constraints are like local instance decls.
* When trying to solve a class constraint, via
TcInteract.matchInstEnv, use the InstEnv from inert_insts
so that we include the local Given forall-constraints
in the lookup. (See TcSMonad.getInstEnvs.)
* TcCanonical.canForAll deals with solving a
forall-constraint. See
Note [Solving a Wanted forall-constraint]
Note [Solving a Wanted forall-constraint]
* We augment the kick-out code to kick out an inert
forall constraint if it can be rewritten by a new
type equality; see TcSMonad.kick_out_rewritable
Still to come
- User manual documentation
- A GHC Proposal
}}}
I'll try to get it up on Phabricator on Monday, unless someone would care
to beat me to it.
Please give it a try!
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/2893#comment:28>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
#14716: indexM-style accessor for arrays?
-------------------------------------+-------------------------------------
Reporter: Zemyla | Owner: (none)
Type: feature | Status: new
request |
Priority: normal | Milestone:
Component: libraries | Version: 8.2.2
(other) |
Keywords: array | Operating System: Unknown/Multiple
Architecture: | Type of failure: None/Unknown
Unknown/Multiple |
Test Case: | Blocked By:
Blocking: | Related Tickets:
Differential Rev(s): | Wiki Page:
-------------------------------------+-------------------------------------
Pretty much everything I've seen being done with basic `Array`s says
something along the lines of "You have to force the argument; otherwise,
you get a thunk that holds a reference to the array". An example of that
is `fromArray` in `Data.Sequence`.
But it really shouldn't be this way. The `Array` from `primitive` and the
`Vector`s from `vector` have ways of obtaining a value from an array that
doesn't leave a thunk hanging around. The basic prototype is
{{{#!hs
indexArrayM :: Monad m => Array a -> Int -> m a
}}}
And having this sort of thing available for standard `Array`s would be
useful because `Array` is one of the first packages users see when they
look for something like arrays in Haskell. Also, it's tagged
`Trustworthy`, unlike `primitive` or `vector`, and there are references to
them in `containers`, which is again a package lots of people use. It'd
also mean that the `Functor`, `Foldable`, and `Traversable` instances
don't leak memory.
As a sort-of-related side note, we should also have a function `(!?)`,
which functions like the similarly-named function in `vector`, and has the
signature
{{{#!hs
(!?) :: (IArray a e, Ix i) => a i e -> i -> Maybe e
}}}
This would, in addition to not leaving a thunk when the `Maybe` is
deconstructed, also eliminate a common use pattern when it comes to
arrays: The user of `(!)` checks the bounds of the array, does something
if it's outside, then passes the index to `(!)` which... checks the bounds
again. Having a function which works like `lookup` on `Map`s would be a
boon here.
Having this work for all `IArray`s, not just `Array`, would require a new
function in the `IArray` typeclass, which might break existing packages
that derive a new `IArray`. However, the function added could be along the
lines of:
{{{#!hs
unsafeAtM :: (Applicative f, Ix i) => a i e -> i -> f e
unsafeAtM a i f = pure (unsafeAt a i)
}}}
which would be a default that, while it doesn't grant the benefits of
using a monadic-type accessor, would ensure the code doesn't break while
the packages that use/derive it are upgraded.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14716>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
#10754: truncate /= double2Int
-------------------------------------+-------------------------------------
Reporter: cblp | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: | Version: 7.10.2
libraries/base |
Keywords: truncate, | Operating System: Unknown/Multiple
double2Int, rewrite, rule |
Architecture: | Type of failure: Incorrect result
Unknown/Multiple | at runtime
Test Case: | Blocked By:
Blocking: | Related Tickets:
Differential Revisions: |
-------------------------------------+-------------------------------------
There is a rule in libraries/base/GHC/Float.hs:
{{{#!hs
"truncate/Double->Int" truncate = double2Int
}}}
But it is not true for some values. Particularly,
{{{#!hs
let infinity = 1/0 :: Double
truncate infinity :: Int == 0
double2Int infinity == -9223372036854775808 -- minBound
}}}
As a result, the value of {{{truncate (1/0 :: Double) :: Int}}} depends on
optimization level.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10754>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler