-
-
Notifications
You must be signed in to change notification settings - Fork 79
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 'foldr1' to the 'Foldable1' typeclass #307
Comments
|
|
@jgm Removing the default value would be nice indeed. However, it doesn't look trivial to do. I see, that even |
Yeah, no base case is simple when: -- base
foldr1 :: (a -> a -> a) -> t a -> a But remove the base case for: -- base
foldr :: (a -> b -> b) -> b -> t a -> b
-- relude
foldr1 :: (a -> b -> b) -> b -> t a -> b Is completely another thing. AFAIK the base cases should not be removed. Everyone expects fold to have a function and then a base case. It is trivial to optimize it & GHC optimizes away that typed Lambda calculus argument order. Base cases are free in provisioning and in code performance. And giving base cases is a good FP practice. Base cases are essential for FP programming, Monoid empty, Nothing, Haskell is non-strict, which means if the base case in the proper place (after constant function arg reuse) - it is free, non-strict language would not arrive into base case if it was not used. It is not deferred the specific case of folds, because When to try to remove the base case too hard, the |
While migrating pretty big codebase (HNix) `foldr1` replacement is the only place I tripped over and was puzzled a bit, the solution was simple, but harder to see because difference was unexpected. Since `relude` is very transparent in migration. It is good to document where the API differences is, to guide people during migration and during use. For more info: kowainik#373 kowainik#307 (comment)
I guess that's my question exactly. Why not have the signature
Foldable1 is for nonempty structures; we have a way to get head and last, so why do we need to specify a base case? This would make
and don't mind specifying a base case, just use |
Because fold for non-empty structures if to take-out the base case would be in an imaginary world we imagine is: -- imaginary
(a -> b -> b) -> t a -> b
-- base
(a -> a -> a) -> t a -> a
-- relude
(a -> b -> b) -> b -> t a -> b If to pick real one - it is the relude one. It is just the same fold, but with NonEmpty power. Because the We actually participate in a years long epic discussion on why that That is why I just decided to submit the note that it is a different implementation. |
I don't mean to engage in a holy war, but what confuses me is this. foldr :: (a -> b -> b) -> b -> t a -> b So what exactly is the difference between |
That |
|
Since |
This almost does not happen in Haskell, especially by thoughtful authors. In Haskell for "more limited domain of application" people often use words "specialized to", "more powerful", "optimized for". As if used properly when needed, special cases optimize better, for some cases |
There are none such. NonEmpty structures always have the base case, that is what to do for
This function is non-total and will raise a runtime exception if the "may only be applied to non-empty structures." which is only said in words, implementation has only "Foldable" constraint - which is an implementation error. If code relies on verbal words said and works only if user turns the proper way to fit the code - that is not user's fault that the code is unsafe and falls. Non-totality in code is one of the most known banes to avoid almost at all cost in the Haskell.
|
Sorry, I'm just not following. Can you give an example where foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b from |
No description provided.
The text was updated successfully, but these errors were encountered: