<div dir="auto">length should be quite well-behaved relative to foldMap:<div dir="auto"><br></div><div dir="auto">length = getSum . foldMap (Sum . const 1)</div><div dir="auto"><br></div><div dir="auto">Another law pretty much everyone agrees on is that *if* f is an instance of Traversable, then</div><div dir="auto"><br></div><div dir="auto">foldMap = foldMapDefault</div><div dir="auto"><br></div><div dir="auto">That leaves a few trouble spots:</div><div dir="auto"><br></div><div dir="auto">1. There are types that some people think shouldn't have Functor/Foldable/Traversable instances at all, or that some people would like to have Functor and maybe even Traversable instances for without wanting Foldable instances. The latter is impossible because of a superclass constraint. One essential issue here seems to be one of perspective: is Foo x y a container of ys, decorated with xs, or is it a container of xs and ys? Different people tend to think about this differently, and thus form different intuitions.</div><div dir="auto"><br></div><div dir="auto">2. There are some functions that the Prelude re-exports from Data.Foldable when it used to export list-specific versions. Some people would like the Prelude to go back to what it did before.</div><div dir="auto"><br></div><div dir="auto">3. It's extremely difficult to formulate useful laws about instances of Foldable that are not also instances of Traversable. This seems to suggest that Foldable itself is an ad hoc convenience rather than a meaningful abstraction of its own.</div><div dir="auto"><div dir="auto"><br><div class="gmail_extra"><br><div class="gmail_quote">On Apr 3, 2017 11:33 AM, "Paolo Giarrusso" <<a href="mailto:p.giarrusso@gmail.com">p.giarrusso@gmail.com</a>> wrote:<br type="attribution"><blockquote class="quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">TL;DR. One (implicit?) assumption in recent debates on `length` seems<br>
to be unfounded, because current docs for Foldable are meant to be<br>
much stronger than their actual language, unless I'm missing<br>
something. Clarifications welcome.<br>
If my understanding is right, I'd suggest somebody fixes the docs. One<br>
point is not clear to me, so at present I could not volunteer to fix<br>
them myself.<br>
<br>
In recent debates, it was assumed or implied that `length` must be equivalent to<br>
<br>
length = length . toList<br>
<br>
>  we also have a kind<br>
> system, so we can ignore the name.<br>
> length :: f a -> Int<br>
> We immediately know that values of the kind (* -> *) slot in to the<br>
> value (f), with a kind checker to ensure we get it correct. Therefore,<br>
> we can easily reason about the length of values of kind ((,) a)<br>
<br>
I don't quite get how that argument is supposed to proceed. However<br>
that's meant, that seems incorrect because length is a typeclass<br>
method, so even the following strawman instance typechecks:<br>
<br>
instance Foldable ((,,) a b) where<br>
  length _ = 42<br>
<br>
I assume this should violate some law, but the relevant law seems to<br>
be forgotten.<br>
<br>
The most constraining language I can find is the following:<br>
<br>
> sum, product, maximum, and minimum should all be essentially equivalent to foldMap forms, such as<br>
> sum = getSum . foldMap Sum<br>
> but may be less defined.<br>
<br>
but (a) `length` is not even mentioned, even if it's intended (b) I<br>
think those should be laws (c) using "should" and "essentially" in<br>
"should all be essentially equivalent", seems too weak. I can infer<br>
the intention, but this seems insufficient to declare<br>
<br>
Docs for `length` don't help either:<br>
<br>
> Returns the size/length of a finite structure as an Int. The default implementation is optimized for structures that are similar to cons-lists, because there is no general way to do better.<br>
<br>
I mean, these docs use the English word "length", so that actually<br>
forbids 42, but that text is too vague to forbid 3 frankly. As I<br>
missing something?<br>
<br>
I also take issue with "may be less defined", and here I'm not sure of<br>
the intention, since that declares<br>
<br>
instance Foldable ((,,) a b) where<br>
  length _ = undefined<br>
<br>
as legal. I imagine the point is about taking the length of partially<br>
undefined structures, but it's not clear to me why a custom `sum`<br>
implementation would be less defined than `sum = getSum . foldMap<br>
Sum`.<br>
<br>
Even ignoring the above instances (which I would never write down), I<br>
can't reason much about my code based on those specifications. This<br>
situation seems unfortunate.<br>
<br>
Cheers,<br>
--<br>
Paolo G. Giarrusso - Ph.D. Student, Tübingen University<br>
<a href="http://ps.informatik.uni-tuebingen.de/team/giarrusso/" rel="noreferrer" target="_blank">http://ps.informatik.uni-<wbr>tuebingen.de/team/giarrusso/</a><br>
______________________________<wbr>_________________<br>
Libraries mailing list<br>
<a href="mailto:Libraries@haskell.org">Libraries@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/libraries</a><br>
</blockquote></div><br></div></div></div></div>