-
Notifications
You must be signed in to change notification settings - Fork 149
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
Drop 1 <= n
constraint from Foldable (Vec n)
and from Traversable (Vec n)
.
#2563
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm somewhat hesitant. Is there a Foldable1
on the horizon? Should we perhaps introduce it ourselves? What motivates this change?
Given that I'm in the middle, I've opted for "Comment". Please sway me.
@@ -0,0 +1 @@ | |||
CHANGED: The `Foldable (Vec n)` instance and `Traversable (Vec n)` instance no longer have the `1 <= n` constraint. `Foldable.{foldr1,foldl1,maximum,minimum}` functions now throw an error at run-/simulation-time, and also at HDL-generation time, for vectors of lenght zero. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CHANGED: The `Foldable (Vec n)` instance and `Traversable (Vec n)` instance no longer have the `1 <= n` constraint. `Foldable.{foldr1,foldl1,maximum,minimum}` functions now throw an error at run-/simulation-time, and also at HDL-generation time, for vectors of lenght zero. | |
CHANGED: The `Foldable (Vec n)` instance and `Traversable (Vec n)` instance no longer have the `1 <= n` constraint. `Foldable.{foldr1,foldl1,maximum,minimum}` functions now throw an error at run-/simulation-time, and also at HDL-generation time, for vectors of length zero. |
foldr = foldr | ||
foldl = foldl | ||
foldr1 f = leToPlus @1 @n $ foldr1 f | ||
foldl1 f = leToPlus @1 @n $ foldl1 f | ||
foldr1 _ Nil = clashCompileError "foldr1: empty list" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
foldr1 _ Nil = clashCompileError "foldr1: empty list" | |
foldr1 _ Nil = clashCompileError "foldr1: empty vector" |
or
foldr1 _ Nil = clashCompileError "foldr1: empty list" | |
foldr1 _ Nil = clashCompileError "foldr1: empty Vec" |
?
It was from a discussion brought on by @gergoerdi on the #clash slack FP channel, so perhaps he can chime in as well. It has also annoyed me that functions using Note that the Finally, |
This makes it easier to use in the prelude itself.
bf8f313
to
d51df7a
Compare
and from `Traversable (Vec n)`. The `Foldable.{foldr1,foldl1,maximum,minimum}` functions now throw an error at run-/simulation-time, and also at HDL-generation time, for vectors of length zero.
d51df7a
to
10f0742
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand why Foldable
is a superclass of Foldable1
. Doesn't that defeat its purpose..?
In any case, these changes look good to me, but I think should export all the Foldable1
functions functions instead of the Foldable
ones. You mentioned minimum
and maximum
, but this also goes for: head
, last
, minimumBy
, and maximumBy
.
I think it makes sense: If you can be folded when there are some extra expectations, then you can be folded when there aren't any. |
product Nil = 1 | ||
product z@Cons{} = fold (*) z |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So multiplication on UFixed 0 n
and SFixed 0 n
/ SFixed 1 n
is a bit weird to begin with, but it does work. However, 1 is not the identity element of multiplication for those types:
>>> :set -XNegativeLiterals
>>> -0.5 :: SFixed 0 8
-0.5
>>> as = -0.5 :> -0.5 :> Nil :: Vec 2 (SFixed 0 8)
>>> product as
0.25
>>> 1 * product as
0.12109375
This might for instance be a problem in
>>> bs = Nil :: Vec 0 (SFixed 0 8)
>>> product (product as :> product bs :> Nil)
0.12109375
The question is, do we care? We seem to be violating the laws of multiplication.
[edit]
To clarify and maybe save you some brain cycles, these types do not have an identity element for multiplication. It would of course have been 1, but that is not representable:
>>> 1 :: SFixed 0 8
0.49609375
[/edit]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess the question is then more whether fromInteger
for SFixed
and UFixed
should saturate or throw an exception when they go out of bounds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit worried about the hidden character of this change. Before, if someone wrote code that say split a vector up so it would end with a Vec 0
somewhere, it would not type-check. Now, it will type-check, but somehow the outcome is halved. That's less apparent than someone trying to stuff a 1 in SFixed 0 8
themselves.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would your suggestion then be to have product
return clashCompileError
for the Nil
case instead then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm more inclined to change fromInteger
to use clashCompileError
for out-of-bounds values, but I'm not saying I have the best answer, just that I think the question is important.
So this is not exactly going to help for this case, but I found it interesting what GHC does for Data.Int
:
topEntity :: Int8
topEntity = 128
gives
FromInteger.hs:7:13: warning: [-Woverflowed-literals]
Literal 128 is out of the Int8 range -128..127
If you are trying to write a large negative literal, use NegativeLiterals
|
7 | topEntity = 128
| ^^^
This warning is on by default.
@martijnbastiaan |
Right @gergoerdi. I was thinking along the lines of "now there's no way you can avoid implementing partial functions", but that's not really relevant. |
The
Foldable.{foldr1,foldl1,maximum,minimum}
functions now throw an error at run-/simulation-time, and also at HDL-generation time, for vectors of length zero.Also moves
clashCompileError
fromClash.Explicit.Prelude
toClash.Magic
.Still TODO: