GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2019-07-07T18:51:01Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/7170Foreign.Concurrent finalizer called twice in some cases2019-07-07T18:51:01ZjoeyadamsForeign.Concurrent finalizer called twice in some casesWhen [Foreign.Concurrent.newForeignPtr](http://hackage.haskell.org/packages/archive/base/latest/doc/html/Foreign-Concurrent.html#v:newForeignPtr) is used, here's a case where the finalizer is called twice:
```
{-# LANGUAGE ForeignFuncti...When [Foreign.Concurrent.newForeignPtr](http://hackage.haskell.org/packages/archive/base/latest/doc/html/Foreign-Concurrent.html#v:newForeignPtr) is used, here's a case where the finalizer is called twice:
```
{-# LANGUAGE ForeignFunctionInterface #-}
import Control.Concurrent
import Control.Exception (bracket)
import Foreign.Ptr (Ptr, intPtrToPtr)
import Foreign.ForeignPtr (ForeignPtr)
import qualified Foreign.Concurrent as FC
import qualified Foreign.ForeignPtr as FP
testForeignPtr_Concurrent :: Ptr a -> IO (ForeignPtr a)
testForeignPtr_Concurrent ptr = FC.newForeignPtr ptr (fin ptr)
fin :: Ptr a -> IO ()
fin ptr = putStrLn $ "finalizing " ++ show ptr
main :: IO ()
main = do
mv <- newEmptyMVar
bracket (testForeignPtr_Concurrent $ intPtrToPtr 1)
FP.finalizeForeignPtr $ \_ ->
-- hang, so the thread and foreign pointer get GCed
takeMVar mv
```
This produces the following output:
```
finalizing 0x0000000000000001
finalizing 0x0000000000000001
foreignptr: thread blocked indefinitely in an MVar operation
```
This happens on GHC 7.4.2 and 7.6.0.20120810, with and without -threaded.
This can easily lead to segfaults when you have an FFI library that does this:
```
create :: IO Object
create = do
ptr <- c_create
CObject <$> newForeignPtr ptr (finalize ptr)
finalize :: Ptr CObject -> IO ()
finalize ptr = do
...
destroy :: Object -> IO ()
destroy (Object fptr) =
finalizeForeignPtr fptr
```
And application code does this:
```
bracket create destroy $ \obj -> do
...
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.4.2 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Runtime System |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Foreign.Concurrent finalizer called twice in some cases","status":"New","operating_system":"","component":"Runtime System","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"When [http://hackage.haskell.org/packages/archive/base/latest/doc/html/Foreign-Concurrent.html#v:newForeignPtr Foreign.Concurrent.newForeignPtr] is used, here's a case where the finalizer is called twice:\r\n\r\n{{{\r\n{-# LANGUAGE ForeignFunctionInterface #-}\r\nimport Control.Concurrent\r\nimport Control.Exception (bracket)\r\nimport Foreign.Ptr (Ptr, intPtrToPtr)\r\nimport Foreign.ForeignPtr (ForeignPtr)\r\nimport qualified Foreign.Concurrent as FC\r\nimport qualified Foreign.ForeignPtr as FP\r\n\r\ntestForeignPtr_Concurrent :: Ptr a -> IO (ForeignPtr a)\r\ntestForeignPtr_Concurrent ptr = FC.newForeignPtr ptr (fin ptr)\r\n\r\nfin :: Ptr a -> IO ()\r\nfin ptr = putStrLn $ \"finalizing \" ++ show ptr\r\n\r\nmain :: IO ()\r\nmain = do\r\n mv <- newEmptyMVar\r\n bracket (testForeignPtr_Concurrent $ intPtrToPtr 1)\r\n FP.finalizeForeignPtr $ \\_ ->\r\n -- hang, so the thread and foreign pointer get GCed\r\n takeMVar mv\r\n}}}\r\n\r\nThis produces the following output:\r\n\r\n{{{\r\nfinalizing 0x0000000000000001\r\nfinalizing 0x0000000000000001\r\nforeignptr: thread blocked indefinitely in an MVar operation\r\n}}}\r\n\r\nThis happens on GHC 7.4.2 and 7.6.0.20120810, with and without -threaded.\r\n\r\nThis can easily lead to segfaults when you have an FFI library that does this:\r\n\r\n{{{\r\ncreate :: IO Object\r\ncreate = do\r\n ptr <- c_create\r\n CObject <$> newForeignPtr ptr (finalize ptr)\r\n\r\nfinalize :: Ptr CObject -> IO ()\r\nfinalize ptr = do\r\n ...\r\n\r\ndestroy :: Object -> IO ()\r\ndestroy (Object fptr) =\r\n finalizeForeignPtr fptr\r\n}}}\r\n\r\nAnd application code does this:\r\n\r\n{{{\r\nbracket create destroy $ \\obj -> do\r\n ...\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1niterianiteriahttps://gitlab.haskell.org/ghc/ghc/-/issues/7077Add an order-reversing newtype to Data.Ord2019-07-07T18:51:30ZAzelAdd an order-reversing newtype to Data.OrdThis is proposal to add an order-reversing newtype to Data.Ord by adding GHC.Exts's one, Down.
You'll find attached a patch implementing this re-export and the conversation thread may be found [here](http://haskell.1045720.n5.nabble.com...This is proposal to add an order-reversing newtype to Data.Ord by adding GHC.Exts's one, Down.
You'll find attached a patch implementing this re-export and the conversation thread may be found [here](http://haskell.1045720.n5.nabble.com/Proposal-add-an-order-reversing-newtype-to-Data-Ord-td5714005.html).
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/base |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Add an order-reversing newtype to Data.Ord","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"","keywords":["ord"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"This is proposal to add an order-reversing newtype to Data.Ord by adding GHC.Exts's one, Down.\r\n\r\nYou'll find attached a patch implementing this re-export and the conversation thread may be found [http://haskell.1045720.n5.nabble.com/Proposal-add-an-order-reversing-newtype-to-Data-Ord-td5714005.html here].","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1pcapriottipcapriottihttps://gitlab.haskell.org/ghc/ghc/-/issues/7067Add alignment-restricted ForeignPtr allocation actions2019-07-07T18:51:33ZnicolastAdd alignment-restricted ForeignPtr allocation actionsWhilst GHC.ForeignPtr exports some actions to allocate buffers containing an element of some type, or of some specific byte-length efficiently, and there's an implementation of newAlignedPinnedByteArray\# used internally, there's no way ...Whilst GHC.ForeignPtr exports some actions to allocate buffers containing an element of some type, or of some specific byte-length efficiently, and there's an implementation of newAlignedPinnedByteArray\# used internally, there's no way to request such buffer of a given size and at a given alignment.
The ability to enforce a specific alignment for some memory buffer is important e.g. when working with SIMD instructions (which is my original use-case). My attempts to work-around the lack of this function failed miserably (with a reproducible test-case) as mentioned in \[1\].
\[1\] http://www.haskell.org/pipermail/glasgow-haskell-users/2012-July/022579.html
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/base |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Add alignment-restricted ForeignPtr allocation actions","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"Whilst GHC.ForeignPtr exports some actions to allocate buffers containing an element of some type, or of some specific byte-length efficiently, and there's an implementation of newAlignedPinnedByteArray# used internally, there's no way to request such buffer of a given size and at a given alignment.\r\n\r\nThe ability to enforce a specific alignment for some memory buffer is important e.g. when working with SIMD instructions (which is my original use-case). My attempts to work-around the lack of this function failed miserably (with a reproducible test-case) as mentioned in [1].\r\n\r\n[1] http://www.haskell.org/pipermail/glasgow-haskell-users/2012-July/022579.html","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1Simon MarlowSimon Marlowhttps://gitlab.haskell.org/ghc/ghc/-/issues/7058Add strict version of modifySTRef2019-07-07T18:51:35ZjoeyadamsAdd strict version of modifySTRefWe added strict versions of modifyIORef and atomicModifyIORef recently (see #5926), and STM has [modifyTVar'](http://hackage.haskell.org/packages/archive/stm/latest/doc/html/Control-Concurrent-STM-TVar.html#v:modifyTVar-39-) since stm-2....We added strict versions of modifyIORef and atomicModifyIORef recently (see #5926), and STM has [modifyTVar'](http://hackage.haskell.org/packages/archive/stm/latest/doc/html/Control-Concurrent-STM-TVar.html#v:modifyTVar-39-) since stm-2.3.
This patch adds `modifySTRef'`, mostly copy-pasted from `modifyIORef'`. My ghc currently doesn't build, so I wasn't able to test it.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.4.2 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/base |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Add strict version of modifySTRef","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"We added strict versions of modifyIORef and atomicModifyIORef recently (see #5926), and STM has [http://hackage.haskell.org/packages/archive/stm/latest/doc/html/Control-Concurrent-STM-TVar.html#v:modifyTVar-39- modifyTVar'] since stm-2.3.\r\n\r\nThis patch adds {{{modifySTRef'}}}, mostly copy-pasted from {{{modifyIORef'}}}. My ghc currently doesn't build, so I wasn't able to test it.","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1Simon MarlowSimon Marlowhttps://gitlab.haskell.org/ghc/ghc/-/issues/7052Numeric types’ Read instances use exponential CPU/memory2019-07-07T18:51:36ZAnders KaseorgNumeric types’ Read instances use exponential CPU/memoryComputing
> read "1e99999999" :: Int -- returns 0
> read "1e99999999" :: Integer -- returns \[REDACTED\]
> read "1e99999999" :: Float -- returns Infinity
> read "1e99999999" :: Double -- returns Infinity
takes rather a lot of CPU time ...Computing
> read "1e99999999" :: Int -- returns 0
> read "1e99999999" :: Integer -- returns \[REDACTED\]
> read "1e99999999" :: Float -- returns Infinity
> read "1e99999999" :: Double -- returns Infinity
takes rather a lot of CPU time and memory, and adding more digits to the exponent makes it take exponentially more. In some applications, this behavior could be exploitable as a denial of service.
I’m not sure what the right solution is for Integer, but clearly all the other cases should be optimized to produce 0 or Infinity very quickly.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.4.2 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/base |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Numeric types’ Read instances use exponential CPU/memory","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Computing\r\n read \"1e99999999\" :: Int -- returns 0\r\n read \"1e99999999\" :: Integer -- returns [REDACTED]\r\n read \"1e99999999\" :: Float -- returns Infinity\r\n read \"1e99999999\" :: Double -- returns Infinity\r\ntakes rather a lot of CPU time and memory, and adding more digits to the exponent makes it take exponentially more. In some applications, this behavior could be exploitable as a denial of service.\r\n\r\nI’m not sure what the right solution is for Integer, but clearly all the other cases should be optimized to produce 0 or Infinity very quickly.","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/7047Add a Functor instance for Control.Exception.Handler2019-07-07T18:51:38ZparcsAdd a Functor instance for Control.Exception.HandlerThis is the ticket that corresponds to the proposal found at http://www.haskell.org/pipermail/libraries/2012-March/017671.html
<details><summary>Trac metadata</summary>
| Trac field | Value |
| --------------------...This is the ticket that corresponds to the proposal found at http://www.haskell.org/pipermail/libraries/2012-March/017671.html
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.4.2 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/base |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Add a Functor instance for Control.Exception.Handler","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"This is the ticket that corresponds to the proposal found at http://www.haskell.org/pipermail/libraries/2012-March/017671.html","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/7041GHC.Real.gcdInt is no longer optimized.2019-07-07T18:51:39ZBertram FelgenhauerGHC.Real.gcdInt is no longer optimized.This is a regression since ghc-7.2, related to #5767. `GHC.Real` defines
```
gcdInt :: Int -> Int -> Int
gcdInt a b = fromIntegral (gcdInteger (fromIntegral a) (fromIntegral b))
```
which used to optimize to `GHC.Integer.Type.gcdInt`. ...This is a regression since ghc-7.2, related to #5767. `GHC.Real` defines
```
gcdInt :: Int -> Int -> Int
gcdInt a b = fromIntegral (gcdInteger (fromIntegral a) (fromIntegral b))
```
which used to optimize to `GHC.Integer.Type.gcdInt`. But since `fromInteger = integerToInt` and `fromIntegral = smallInteger` are no longer inlined, this optimization is lost. This results in unecessary allocations.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.5 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/base |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"GHC.Real.gcdInt is no longer optimized.","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.5","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"This is a regression since ghc-7.2, related to #5767. {{{GHC.Real}}} defines\r\n\r\n{{{\r\ngcdInt :: Int -> Int -> Int\r\ngcdInt a b = fromIntegral (gcdInteger (fromIntegral a) (fromIntegral b))\r\n}}}\r\n\r\nwhich used to optimize to {{{GHC.Integer.Type.gcdInt}}}. But since {{{fromInteger = integerToInt}}} and {{{fromIntegral = smallInteger}}} are no longer inlined, this optimization is lost. This results in unecessary allocations.","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1Ian Lynagh <igloo@earth.li>Ian Lynagh <igloo@earth.li>https://gitlab.haskell.org/ghc/ghc/-/issues/7029Add System.Environment.getExecutablePath2019-07-07T18:51:42ZtibbeAdd System.Environment.getExecutablePathAs agreed after the corresponding libraries@ discussion (http://thread.gmane.org/gmane.comp.lang.haskell.libraries/17368) we should add `System.Environment.getExecutablePath`. Attached is an implementation for OS X, Linux, and Windows, w...As agreed after the corresponding libraries@ discussion (http://thread.gmane.org/gmane.comp.lang.haskell.libraries/17368) we should add `System.Environment.getExecutablePath`. Attached is an implementation for OS X, Linux, and Windows, with a fallback to argv\[0\] on other platforms.
The Windows implementation was written without access to a Windows machine, so someone will need to test it on Windows to make sure it compiles/works.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.4.2 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/base |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Add System.Environment.getExecutablePath","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"As agreed after the corresponding libraries@ discussion (http://thread.gmane.org/gmane.comp.lang.haskell.libraries/17368) we should add `System.Environment.getExecutablePath`. Attached is an implementation for OS X, Linux, and Windows, with a fallback to argv[0] on other platforms.\r\n\r\nThe Windows implementation was written without access to a Windows machine, so someone will need to test it on Windows to make sure it compiles/works.","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/7012ForeignPtrContents isn't exported2019-07-07T18:51:48Zrl@cse.unsw.edu.auForeignPtrContents isn't exportedGHC.ForeignPtr doesn't export ForeignPtrContents. This means that this function can't be given a signature in user code:
f (ForeignPtr _ x) = x
ForeignPtrContents should be exported, at least abstractly, although exporting the construc...GHC.ForeignPtr doesn't export ForeignPtrContents. This means that this function can't be given a signature in user code:
f (ForeignPtr _ x) = x
ForeignPtrContents should be exported, at least abstractly, although exporting the constructors, too, would be useful for low-level code.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ----------------- |
| Version | 7.4.2 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries (other) |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"ForeignPtrContents isn't exported","status":"New","operating_system":"","component":"libraries (other)","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"GHC.ForeignPtr doesn't export ForeignPtrContents. This means that this function can't be given a signature in user code:\r\n\r\nf (ForeignPtr _ x) = x\r\n\r\nForeignPtrContents should be exported, at least abstractly, although exporting the constructors, too, would be useful for low-level code.","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/6136gettimeofday should not be used to schedule timeouts2019-07-07T18:51:59ZDanielWaterworthgettimeofday should not be used to schedule timeoutsFrom what I can tell, [getCurrentTime](http://hackage.haskell.org/packages/archive/base/latest/doc/html/src/GHC-Event-Clock.html#getCurrentTime) uses gettimeofday and is used in [registerTimeout](http://hackage.haskell.org/packages/archi...From what I can tell, [getCurrentTime](http://hackage.haskell.org/packages/archive/base/latest/doc/html/src/GHC-Event-Clock.html#getCurrentTime) uses gettimeofday and is used in [registerTimeout](http://hackage.haskell.org/packages/archive/base/latest/doc/html/src/GHC-Event-Manager.html#registerTimeout) for the purpose of scheduling timeouts. I recommend reading [this](http://blog.habets.pp.se/2010/09/gettimeofday-should-never-be-used-to-measure-time) for an explanation of why this isn't a good idea.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.4.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/base |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"gettimeofday should not be used to schedule timeouts","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"From what I can tell, [http://hackage.haskell.org/packages/archive/base/latest/doc/html/src/GHC-Event-Clock.html#getCurrentTime getCurrentTime] uses gettimeofday and is used in [http://hackage.haskell.org/packages/archive/base/latest/doc/html/src/GHC-Event-Manager.html#registerTimeout registerTimeout] for the purpose of scheduling timeouts. I recommend reading [http://blog.habets.pp.se/2010/09/gettimeofday-should-never-be-used-to-measure-time this] for an explanation of why this isn't a good idea.","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/5963Fixed format floating point conversion does not round to even2019-07-07T18:52:50Zlennart@augustsson.netFixed format floating point conversion does not round to evenConversion of floating point numbers to a fixed numbers of decimals should use round-to-even rather that rounding up when the number is right between two possible results.
E.g., printf "%.1f" 0.45 should produce "0.4" rather than "0.5"....Conversion of floating point numbers to a fixed numbers of decimals should use round-to-even rather that rounding up when the number is right between two possible results.
E.g., printf "%.1f" 0.45 should produce "0.4" rather than "0.5".
The heart of the problem is in libraries/base/GHC/Float.lhs.
The roundTo function should be replaced by this
```
roundTo :: Int -> Int -> [Int] -> (Int,[Int])
roundTo base d is =
case f d True is of
x@(0,_) -> x
(1,xs) -> (1, 1:xs)
_ -> error "roundTo: bad Value"
where
b2 = base `quot` 2
f n _ [] = (0, replicate n 0)
f 0 e (x:xs) | x == b2 && e && all (== 0) xs = (0, []) -- Round to even when at exactly half the base
| otherwise = (if x >= b2 then 1 else 0, [])
f n _ (i:xs)
| i' == base = (1,0:ds)
| otherwise = (0,i':ds)
where
(c,ds) = f (n-1) (even i) xs
i' = c + i
```
I also (as the original author of the code) note that the large parts of that module was taken verbatim from the hbc libraries without attribution. :)
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.4.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/base |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Fixed format floating point conversion does not round to even","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Conversion of floating point numbers to a fixed numbers of decimals should use round-to-even rather that rounding up when the number is right between two possible results.\r\n\r\nE.g., printf \"%.1f\" 0.45 should produce \"0.4\" rather than \"0.5\".\r\n\r\nThe heart of the problem is in libraries/base/GHC/Float.lhs.\r\nThe roundTo function should be replaced by this\r\n\r\n{{{\r\n\r\nroundTo :: Int -> Int -> [Int] -> (Int,[Int])\r\nroundTo base d is =\r\n case f d True is of\r\n x@(0,_) -> x\r\n (1,xs) -> (1, 1:xs)\r\n _ -> error \"roundTo: bad Value\"\r\n where\r\n b2 = base `quot` 2\r\n\r\n f n _ [] = (0, replicate n 0)\r\n f 0 e (x:xs) | x == b2 && e && all (== 0) xs = (0, []) -- Round to even when at exactly half the base\r\n | otherwise = (if x >= b2 then 1 else 0, [])\r\n f n _ (i:xs)\r\n | i' == base = (1,0:ds)\r\n | otherwise = (0,i':ds)\r\n where\r\n (c,ds) = f (n-1) (even i) xs\r\n i' = c + i\r\n}}}\r\n\r\nI also (as the original author of the code) note that the large parts of that module was taken verbatim from the hbc libraries without attribution. :)\r\n","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/5930add System.Environment.lookupEnv which returns Maybe instead of an exception2019-07-07T18:52:57Zelaforgeadd System.Environment.lookupEnv which returns Maybe instead of an exceptiongetEnv throws an exception when the key isn't found, which is surprising and inconvenient. I'd prefer to change the signature of getEnv to return Maybe, but that will break people's code, so I'll settle for a new lookupEnv function.
It'...getEnv throws an exception when the key isn't found, which is surprising and inconvenient. I'd prefer to change the signature of getEnv to return Maybe, but that will break people's code, so I'll settle for a new lookupEnv function.
It's been discussed on libraries\@haskell.org and there was unanimous support.
Patches attached, the first cleans up mixed tabs and spaces (which I understand has been happening in ghc lately). The second adds the new function. Unfortunately I still can't get ghc to compile so it's untested for now. I'll keep trying with GHC, but I don't have a windows machine for testing.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.4.1 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/base |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"add System.Environment.lookupEnv which returns Maybe instead of an exception","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"getEnv throws an exception when the key isn't found, which is surprising and inconvenient. I'd prefer to change the signature of getEnv to return Maybe, but that will break people's code, so I'll settle for a new lookupEnv function.\r\n\r\nIt's been discussed on libraries@haskell.org and there was unanimous support.\r\n\r\nPatches attached, the first cleans up mixed tabs and spaces (which I understand has been happening in ghc lately). The second adds the new function. Unfortunately I still can't get ghc to compile so it's untested for now. I'll keep trying with GHC, but I don't have a windows machine for testing.","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1pcapriottipcapriottihttps://gitlab.haskell.org/ghc/ghc/-/issues/5926Add strict versions of modifyIORef and atomicModifyIORef2023-02-20T02:32:24ZjoeyadamsAdd strict versions of modifyIORef and atomicModifyIORefIt is easy to misuse modifyIORef and atomicModifyIORef due to their lack of strictness. For example, if you use an IORef as a counter, use modifyIORef to increment it, and never evaluate the value until the very end, your program will le...It is easy to misuse modifyIORef and atomicModifyIORef due to their lack of strictness. For example, if you use an IORef as a counter, use modifyIORef to increment it, and never evaluate the value until the very end, your program will leak memory, and you may even get a stack overflow:
```
ref <- newIORef 0
replicateM_ 1000000 $ modifyIORef ref (+1)
readIORef ref >>= print
```
Today, I found a [space leak in the tls package](https://github.com/vincenthz/hs-tls/pull/8). Repeatedly calling sendData would leak memory. It didn't take me long to find the cause once I noticed a module named "Measurement" used for gathering connection statistics. It used modifyIORef to update the Measurement structure. When I changed it to this:
```
x <- readIORef (ctxMeasurement ctx)
writeIORef (ctxMeasurement ctx) $! f x
```
the space leak went away.
A more subtle mistake can be made using atomicModifyIORef. Can you spot the problem with this code?
```
atomicModifyIORef ref (\_ -> (new_value, ()))
```
It's not incrementing anything, it's just replacing the value. However, it's still deferring evaluation of the function. This mistake was pointed out in [The Monad.Reader Issue 19](http://themonadreader.files.wordpress.com/2011/10/issue19.pdf), where they suggested the following idiom:
```
x <- atomicModifyIORef ref (\_ -> (new_value, ()))
x `seq` return ()
```
Thus, I believe there should be strict variants of modifyIORef and atomicModifyIORef, if only to warn programmers of these pitfalls.
`modifyIORef'` is pretty straightforward: force the result of applying the function:
```
modifyIORef' ref f = do
x <- readIORef ref
let x' = f x
x' `seq` writeIORef ref x'
```
The only question is: would it be better to force `x'` after `writeIORef` instead of before it, in case a caller is trying to share the IORef among threads (which they shouldn't be)?
`atomicModifyIORef` is less straightforward. Should we force the values themselves? It is possible to avoid the space leak above without forcing either the new value or the return value:
```
atomicModifyIORef' :: IORef a -> (a -> (a,b)) -> IO b
atomicModifyIORef' ref f = do
p <- atomicModifyIORef ref (\a -> let p = f a in (fst p, p))
p `seq` return (snd p)
```
It also allows `f` to decide what to force. For example, with this definition of atomicModifyIORef', the following program prints 10000000 and does not leak memory:
```
ref <- newIORef 0
replicateM_ 10000000 $
atomicModifyIORef' ref
(\n -> let n' = n + 1
in n' `seq` (n', undefined))
readIORef ref >>= print
```
In the attached patch, I didn't implement atomicModifyIORef' this way. Instead, I made it force both the old and new values, and added a separate function called atomicWriteIORef that has the same signature as writeIORef, but is based on atomicModifyIORef.
I believe the real value of such functions is to warn programmers about these pitfalls.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.4.1 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/base |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Add strict versions of modifyIORef and atomicModifyIORef","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"It is easy to misuse modifyIORef and atomicModifyIORef due to their lack of strictness. For example, if you use an IORef as a counter, use modifyIORef to increment it, and never evaluate the value until the very end, your program will leak memory, and you may even get a stack overflow:\r\n\r\n{{{\r\nref <- newIORef 0\r\nreplicateM_ 1000000 $ modifyIORef ref (+1)\r\nreadIORef ref >>= print\r\n}}}\r\n\r\nToday, I found a [https://github.com/vincenthz/hs-tls/pull/8 space leak in the tls package]. Repeatedly calling sendData would leak memory. It didn't take me long to find the cause once I noticed a module named \"Measurement\" used for gathering connection statistics. It used modifyIORef to update the Measurement structure. When I changed it to this:\r\n\r\n{{{\r\nx <- readIORef (ctxMeasurement ctx)\r\nwriteIORef (ctxMeasurement ctx) $! f x\r\n}}}\r\n\r\nthe space leak went away.\r\n\r\nA more subtle mistake can be made using atomicModifyIORef. Can you spot the problem with this code?\r\n\r\n{{{\r\natomicModifyIORef ref (\\_ -> (new_value, ()))\r\n}}}\r\n\r\nIt's not incrementing anything, it's just replacing the value. However, it's still deferring evaluation of the function. This mistake was pointed out in [http://themonadreader.files.wordpress.com/2011/10/issue19.pdf The Monad.Reader Issue 19], where they suggested the following idiom:\r\n\r\n{{{\r\nx <- atomicModifyIORef ref (\\_ -> (new_value, ()))\r\nx `seq` return ()\r\n}}}\r\n\r\nThus, I believe there should be strict variants of modifyIORef and atomicModifyIORef, if only to warn programmers of these pitfalls.\r\n\r\n{{{modifyIORef'}}} is pretty straightforward: force the result of applying the function:\r\n\r\n{{{\r\nmodifyIORef' ref f = do\r\n x <- readIORef ref\r\n let x' = f x\r\n x' `seq` writeIORef ref x'\r\n}}}\r\n\r\nThe only question is: would it be better to force `x'` after `writeIORef` instead of before it, in case a caller is trying to share the IORef among threads (which they shouldn't be)?\r\n\r\n{{{atomicModifyIORef}}} is less straightforward. Should we force the values themselves? It is possible to avoid the space leak above without forcing either the new value or the return value:\r\n\r\n{{{\r\natomicModifyIORef' :: IORef a -> (a -> (a,b)) -> IO b\r\natomicModifyIORef' ref f = do\r\n p <- atomicModifyIORef ref (\\a -> let p = f a in (fst p, p))\r\n p `seq` return (snd p)\r\n}}}\r\n\r\nIt also allows {{{f}}} to decide what to force. For example, with this definition of atomicModifyIORef', the following program prints 10000000 and does not leak memory:\r\n\r\n{{{\r\nref <- newIORef 0\r\nreplicateM_ 10000000 $\r\n atomicModifyIORef' ref\r\n (\\n -> let n' = n + 1\r\n in n' `seq` (n', undefined))\r\nreadIORef ref >>= print\r\n}}}\r\n\r\nIn the attached patch, I didn't implement atomicModifyIORef' this way. Instead, I made it force both the old and new values, and added a separate function called atomicWriteIORef that has the same signature as writeIORef, but is based on atomicModifyIORef.\r\n\r\nI believe the real value of such functions is to warn programmers about these pitfalls.","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1Simon MarlowSimon Marlowhttps://gitlab.haskell.org/ghc/ghc/-/issues/5741openFile should fail if null bytes are in the argument2019-07-07T18:53:48ZVeinoropenFile should fail if null bytes are in the argumentIf the argument to openFile contains a null byte, right now it silently truncates everything after the null byte. This could lead to a vulnerability if the programmer relies on the presence of an extension such as ".cfg" to prevent peopl...If the argument to openFile contains a null byte, right now it silently truncates everything after the null byte. This could lead to a vulnerability if the programmer relies on the presence of an extension such as ".cfg" to prevent people from reading in, say, /etc/passwd.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.2.1 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/base |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"openFile should fail if null bytes are in the argument","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.2.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"If the argument to openFile contains a null byte, right now it silently truncates everything after the null byte. This could lead to a vulnerability if the programmer relies on the presence of an extension such as \".cfg\" to prevent people from reading in, say, /etc/passwd.","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/5699Use sharing in the Alternative instance of Maybe2019-07-07T18:53:59ZbasvandijkUse sharing in the Alternative instance of MaybeThe `<|>` method of the `Alternative` instance of `Maybe` does not share its first argument when it could:
```
instance Alternative Maybe where
empty = Nothing
Nothing <|> p = p
Just x <|> _ = Just x
```
I propose to share...The `<|>` method of the `Alternative` instance of `Maybe` does not share its first argument when it could:
```
instance Alternative Maybe where
empty = Nothing
Nothing <|> p = p
Just x <|> _ = Just x
```
I propose to share this argument:
```
instance Alternative Maybe where
empty = Nothing
Nothing <|> r = r
l <|> _ = l
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.2.1 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/base |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Use sharing in the Alternative instance of Maybe","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.2.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"The `<|>` method of the `Alternative` instance of `Maybe` does not share its first argument when it could:\r\n\r\n{{{\r\ninstance Alternative Maybe where\r\n empty = Nothing\r\n Nothing <|> p = p\r\n Just x <|> _ = Just x\r\n}}}\r\n\r\nI propose to share this argument:\r\n\r\n{{{\r\ninstance Alternative Maybe where\r\n empty = Nothing\r\n Nothing <|> r = r\r\n l <|> _ = l\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/5683bug in signum function2019-07-07T18:54:03Ztristes_tigresbug in signum functionIEE754 standard states, that every floating point operation involving a NaN should produce NaN. However, in GHC 7.0.3 (in the current Haskell platform) evaluating\[\[BR\]\]
> signum (0.0/0.0)\[\[BR\]\]
produces -1
<details><summary>Tr...IEE754 standard states, that every floating point operation involving a NaN should produce NaN. However, in GHC 7.0.3 (in the current Haskell platform) evaluating\[\[BR\]\]
> signum (0.0/0.0)\[\[BR\]\]
produces -1
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.0.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Prelude |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"bug in signum function","status":"New","operating_system":"","component":"Prelude","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.0.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"IEE754 standard states, that every floating point operation involving a NaN should produce NaN. However, in GHC 7.0.3 (in the current Haskell platform) evaluating[[BR]]\r\n> signum (0.0/0.0)[[BR]]\r\nproduces -1\r\n","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/5679Provide Arrow lift functions for Control.Arrow2019-07-07T18:54:05ZA1kmmProvide Arrow lift functions for Control.ArrowIt is currently difficult to build complex datastructures by combining arrows, because there are no lift functions defined on Arrow. These can be built easily from the class functions:
```
liftArrow :: Arrow a => (c -> d) -> a b c -> a ...It is currently difficult to build complex datastructures by combining arrows, because there are no lift functions defined on Arrow. These can be built easily from the class functions:
```
liftArrow :: Arrow a => (c -> d) -> a b c -> a b d
liftArrow = (^>>)
liftArrow2 :: Arrow a => (c -> c' -> d) -> a b c -> a b c' -> a b d
liftArrow2 f a1 a2 = arr (\a -> (a, a)) >>> (a1 *** a2) >>> arr (\(a, b) -> f a b)
liftArrow3 :: Arrow a => (c -> c' -> c'' -> d) -> a b c -> a b c' -> a b c'' -> a b d
liftArrow3 f a1 a2 a3 = arr (\a -> (a, (a, a))) >>> (a1 *** a2 *** a3) >>> arr (\(a, (b, c)) -> f a b c)
liftArrow4 :: Arrow a => (c -> c' -> c'' -> c''' -> d) -> a b c -> a b c' -> a b c'' -> a b c''' -> a b d
liftArrow4 f a1 a2 a3 a4 = arr (\a -> (a, (a, (a, a)))) >>> (a1 *** a2 *** a3 *** a4) >>> arr (\(a, (b, (c, d))) -> f a b c d)
liftArrow5 :: Arrow a => (c -> c' -> c'' -> c''' -> c'''' -> d) -> a b c -> a b c' -> a b c'' -> a b c''' -> a b d
liftArrow5 f a1 a2 a3 a4 a5 = arr (\a -> (a, (a, (a, (a, a))))) >>> (a1 *** a2 *** a3 *** a4 *** a5) >>> arr (\(a, (b, (c, (d, e)))) -> f a b c d e)
```
I suggest these be added to Control.Arrow.
elliott suggested (on \#haskell on Freenode) that something like arr2 = arr . uncurry could be defined as a building block, from which the lift functions could be defined.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.2.1 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/base |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Provide Arrow lift functions for Control.Arrow","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.2.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"It is currently difficult to build complex datastructures by combining arrows, because there are no lift functions defined on Arrow. These can be built easily from the class functions:\r\n\r\n{{{\r\nliftArrow :: Arrow a => (c -> d) -> a b c -> a b d\r\nliftArrow = (^>>)\r\nliftArrow2 :: Arrow a => (c -> c' -> d) -> a b c -> a b c' -> a b d\r\nliftArrow2 f a1 a2 = arr (\\a -> (a, a)) >>> (a1 *** a2) >>> arr (\\(a, b) -> f a b)\r\nliftArrow3 :: Arrow a => (c -> c' -> c'' -> d) -> a b c -> a b c' -> a b c'' -> a b d\r\nliftArrow3 f a1 a2 a3 = arr (\\a -> (a, (a, a))) >>> (a1 *** a2 *** a3) >>> arr (\\(a, (b, c)) -> f a b c)\r\nliftArrow4 :: Arrow a => (c -> c' -> c'' -> c''' -> d) -> a b c -> a b c' -> a b c'' -> a b c''' -> a b d\r\nliftArrow4 f a1 a2 a3 a4 = arr (\\a -> (a, (a, (a, a)))) >>> (a1 *** a2 *** a3 *** a4) >>> arr (\\(a, (b, (c, d))) -> f a b c d)\r\nliftArrow5 :: Arrow a => (c -> c' -> c'' -> c''' -> c'''' -> d) -> a b c -> a b c' -> a b c'' -> a b c''' -> a b d\r\nliftArrow5 f a1 a2 a3 a4 a5 = arr (\\a -> (a, (a, (a, (a, a))))) >>> (a1 *** a2 *** a3 *** a4 *** a5) >>> arr (\\(a, (b, (c, (d, e)))) -> f a b c d e)\r\n}}}\r\n\r\nI suggest these be added to Control.Arrow.\r\n\r\nelliott suggested (on #haskell on Freenode) that something like arr2 = arr . uncurry could be defined as a building block, from which the lift functions could be defined.","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/5667Data.Unique.Unique and Data.Graph.SCC are not instances of Show2019-07-07T18:54:07ZjewillcoData.Unique.Unique and Data.Graph.SCC are not instances of ShowThese two types are not currently instances of `Show`, and having that would be useful for debugging. The instances can both be derived (even using `deriving instance` in a separate module).
<details><summary>Trac metadata</summary>
| ...These two types are not currently instances of `Show`, and having that would be useful for debugging. The instances can both be derived (even using `deriving instance` in a separate module).
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.2.1 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/base |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Data.Unique.Unique and Data.Graph.SCC are not instances of Show","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.2.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"These two types are not currently instances of `Show`, and having that would be useful for debugging. The instances can both be derived (even using `deriving instance` in a separate module).","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/5627Proposal: Add Applicative instances for the remaining monads in base2019-07-07T18:54:18ZbasvandijkProposal: Add Applicative instances for the remaining monads in baseThe only public monads in `base` that don't have `Applicative` instances
yet are: `ReadP`, `ReadPrec` and `ArrowMonad`. Because of the rule of least
surprise I would like to propose adding `Applicative` instances for
these monads.
## Pr...The only public monads in `base` that don't have `Applicative` instances
yet are: `ReadP`, `ReadPrec` and `ArrowMonad`. Because of the rule of least
surprise I would like to propose adding `Applicative` instances for
these monads.
## Proposal
Concretely I would like to propose adding the following to `Control.Applicative`:
```
instance Applicative ReadP where
pure = return
(<*>) = ap
instance Alternative ReadP where
empty = mzero
(<|>) = mplus
instance Applicative ReadPrec where
pure = return
(<*>) = ap
instance Alternative ReadPrec where
empty = mzero
(<|>) = mplus
instance Arrow a => Applicative (ArrowMonad a) where
pure x = ArrowMonad (arr (const x))
ArrowMonad f <*> ArrowMonad x = ArrowMonad (f &&& x >>> arr (uncurry id))
instance ArrowPlus a => Alternative (ArrowMonad a) where
empty = ArrowMonad zeroArrow
ArrowMonad x <|> ArrowMonad y = ArrowMonad (x <+> y)
```
And adding the following to `Control.Arrow`:
```
instance Arrow a => Functor (ArrowMonad a) where
fmap f (ArrowMonad m) = ArrowMonad $ m >>> arr f
instance (ArrowApply a, ArrowPlus a) => MonadPlus (ArrowMonad a) where
mzero = ArrowMonad zeroArrow
ArrowMonad x `mplus` ArrowMonad y = ArrowMonad (x <+> y)
```
## Discussion deadline
I don't think this is a controversial proposal and so I don't expect objections. Can we bend the rules a bit and shorten the discussion period so this can be integrated into the base library that comes with the upcoming `ghc-7.4`?
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.2.1 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/base |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Proposal: Add Applicative instances for the remaining monads in base","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.2.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"The only public monads in `base` that don't have `Applicative` instances\r\nyet are: `ReadP`, `ReadPrec` and `ArrowMonad`. Because of the rule of least\r\nsurprise I would like to propose adding `Applicative` instances for\r\nthese monads.\r\n\r\n== Proposal ==\r\n\r\nConcretely I would like to propose adding the following to `Control.Applicative`:\r\n\r\n{{{\r\ninstance Applicative ReadP where\r\n pure = return\r\n (<*>) = ap\r\n\r\ninstance Alternative ReadP where\r\n empty = mzero\r\n (<|>) = mplus\r\n\r\ninstance Applicative ReadPrec where\r\n pure = return\r\n (<*>) = ap\r\n\r\ninstance Alternative ReadPrec where\r\n empty = mzero\r\n (<|>) = mplus\r\n\r\ninstance Arrow a => Applicative (ArrowMonad a) where\r\n pure x = ArrowMonad (arr (const x))\r\n ArrowMonad f <*> ArrowMonad x = ArrowMonad (f &&& x >>> arr (uncurry id))\r\n\r\ninstance ArrowPlus a => Alternative (ArrowMonad a) where\r\n empty = ArrowMonad zeroArrow\r\n ArrowMonad x <|> ArrowMonad y = ArrowMonad (x <+> y)\r\n}}}\r\n\r\nAnd adding the following to `Control.Arrow`:\r\n\r\n{{{\r\ninstance Arrow a => Functor (ArrowMonad a) where\r\n fmap f (ArrowMonad m) = ArrowMonad $ m >>> arr f\r\n\r\ninstance (ArrowApply a, ArrowPlus a) => MonadPlus (ArrowMonad a) where\r\n mzero = ArrowMonad zeroArrow\r\n ArrowMonad x `mplus` ArrowMonad y = ArrowMonad (x <+> y)\r\n}}}\r\n\r\n== Discussion deadline ==\r\n\r\nI don't think this is a controversial proposal and so I don't expect objections. Can we bend the rules a bit and shorten the discussion period so this can be integrated into the base library that comes with the upcoming `ghc-7.4`?","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/5593Proposal: Remove Num superclass of Bits2019-07-07T18:54:35ZbasvandijkProposal: Remove Num superclass of BitsThis ticket summarizes the [discussion](http://www.haskell.org/pipermail/libraries/2011-October/016899.html) on the proposal to remove the `Num` superclass of the `Bits` type class.
The proposal is to:
- Remove the `Num` superclass of ...This ticket summarizes the [discussion](http://www.haskell.org/pipermail/libraries/2011-October/016899.html) on the proposal to remove the `Num` superclass of the `Bits` type class.
The proposal is to:
- Remove the `Num` superclass of the `Bits` type class.
- Remove the default implementations of `bit`, `testBit` and `popCount` since they use methods of `Num`.
- Export the following convenience functions from `Data.Bits`:
```
bitDefault :: (Bits a, Num a) => Int -> a
bitDefault i = 1 `shiftL` i
testBitDefault :: (Bits a, Num a) => a -> Int -> Bool
testBitDefault x i = (x .&. bit i) /= 0
popCountDefault :: (Bits a, Num a) => a -> Int
popCountDefault = go 0
where
go !c 0 = c
go c w = go (c+1) (w .&. w - 1) -- clear the least significant
```
Attached are tickets for `base` and `ghc`.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.2.1 |
| Type | Task |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/base |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Proposal: Remove Num superclass of Bits","status":"New","operating_system":"","component":"libraries/base","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.2.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Task","description":"This ticket summarizes the [http://www.haskell.org/pipermail/libraries/2011-October/016899.html discussion] on the proposal to remove the `Num` superclass of the `Bits` type class.\r\n\r\nThe proposal is to:\r\n\r\n * Remove the `Num` superclass of the `Bits` type class.\r\n\r\n * Remove the default implementations of `bit`, `testBit` and `popCount` since they use methods of `Num`.\r\n\r\n * Export the following convenience functions from `Data.Bits`:\r\n\r\n{{{\r\nbitDefault :: (Bits a, Num a) => Int -> a\r\nbitDefault i = 1 `shiftL` i\r\n\r\ntestBitDefault :: (Bits a, Num a) => a -> Int -> Bool\r\ntestBitDefault x i = (x .&. bit i) /= 0\r\n\r\npopCountDefault :: (Bits a, Num a) => a -> Int\r\npopCountDefault = go 0\r\n where\r\n go !c 0 = c\r\n go c w = go (c+1) (w .&. w - 1) -- clear the least significant\r\n}}}\r\n\r\nAttached are tickets for `base` and `ghc`.","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1