-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a suitable {-# WARNING in "x-partial" ... #-} to Data.List.{init,last} #292
Comments
The It feels that foo [] = something
foo xs = somethingElseWith (last xs) it not uncommon pattern in older code, because writing that safely was quite inconvenient using just foo [] = something
foo (x : xs) = somethingElseWith (NonEmpty.last (x :| xs)) i.e. above It would be really helpful to see in how many modules in |
Nowadays one can write |
In that light, simply adding a proposed warning seems to be inline with recent-ish CLC views. |
We are past GHC 9.12 / base-4.21 fork, so the proposed warning can land no sooner than base-4.22, making |
@mpilgrem would you like to prepare an MR for this? |
@Bodigrim, I have created: On avoiding warnings within the GHC repository, I added |
@Bodigrim, may I ask for a bit a advice? I have run into package There is a I am not sure what I should be proposing to change, to try to make the changes that will allow GHC's CI to pass for my MR. I think that all is needed, in the immediate instance, is for the relevant module in {-# LANGUAGE CPP #-}
#if MIN_VERSION_GLASGOW_HASKELL(9,8,1,0)
-- For init and last in trimTrailing
{-# OPTIONS_GHC -Wno-x-partial #-}
#endif |
|
I see that the proposed warning directs users to If you would like to check the Core: https://play.haskell.org/saved/ySiaRuho |
For information: the origin of the text of the proposed compiler warning is the existing warning in the Haddock documentation for |
I have no experience in measuring, or optimising, Haskell code performance, but (in the light of @meooow25's comments) I tried to apply the module Main (main) where
import Criterion.Main
import Data.List ( unsnoc )
import Data.List.NonEmpty ( NonEmpty (..) )
import qualified Data.List.NonEmpty as NE
partial :: String -> Maybe (String, Char)
partial "" = Nothing
partial s = Just (init s, last s)
total1 :: String -> Maybe (String, Char)
total1 = unsnoc
total2 :: String -> Maybe (String, Char)
total2 "" = Nothing
total2 (c:cs) = let s = c :| cs in Just (NE.init s, NE.last s)
main :: IO ()
main = defaultMain
[ bgroup "last" [ bench "partial" $ nf partial "Hello! World"
, bench "total1" $ nf total1 "Hello! World"
, bench "total2" $ nf total2 "Hello! World"
]
]
The results were typically like the following:
I was surprised that The introduction of |
I repeated my
|
By way of update, the merge request pipeline for the MR is now all green (following some false starts). The existing import Data.List.NonEmpty ( NonEmpty (..) )
import qualified Data.List.NonEmpty as NE
unsnoc :: [a] -> Maybe ([a], a)
unsnoc [] = Nothing
unsnoc (x:xs) = let l = x :| xs in Just (NE.init l, NE.last l) If they are not wrong, it may be that there should be a new issue for the CLC on that topic, with this issue dependent on the resolution of that issue. |
These are cheap, short-living allocations in the nursery, so they are not materially worse than O(n) time. @mpilgrem The existing implementation of Sacrificing list fusion is probably reasonable: in cases where list fusion used to happen we will lose one allocation on materializing Traversing the list twice is less palatable to my taste, because it can double maximum memory residence: we would materialise the input in full while computing Could you possibly benchmark an implementation of |
Following the past decisions in respect of
Data.List.head
andData.List.tail
in:implemented in
base-4.19.0.0
(GHC 9.8.1), which also addedData.List.unsnoc
, I propose, for consistency, that the same idea is extended toData.List.init
andData.List.last
. Their Haddock documentation has warned that they are partial and suggested alternatives sincebase-4.17.0.0
(GHC 9.4.1).The basis for the proposal is purely consistency of treatment of
Data.List.{head,tail,init,last}
. It seems to me that the principal merits and drawbacks applicable tohead
andtail
, discussed at some length in the past approved proposals, are equally applicable toinit
andlast
.@Bodigrim, on introducing #87 (at #87 (comment)), gave as a reason that it was not extended then to
init
orlast
that doing so would requireData.List.unsnoc
first. That barrier no longer applies.In case it is relevant, I note:
base
are defined in terms ofData.List.init
orData.List.last
. For example,Data.List.NonEmpty.init
:Paths_<package_name>.hs
module makes use ofData.List.last
- see https://hackage.haskell.org/package/Cabal-3.14.0.0/src/src/Distribution/Simple/Build/PathsModule/Z.hs.The text was updated successfully, but these errors were encountered: