[Haskell-cafe] Ambiguous types
juan.casanova at ed.ac.uk
Wed Aug 7 12:53:17 UTC 2019
There are two important things to say about your e-mail, but one is a
lot more important than the other.
> And no, I don't want the general code to be specific for lists, thus
> no extra type
> signatures or changes to make it more list of Ints.
You did not understand my (and Paolino's) point about using lists. By
using lists *internally* you're not making it less generic. The
function still works for any foldable. But you are building another
foldable *within your function* as a way to check for duplication,
that isn't returned. When you build an element, you need to specify
it's type (or use a function passed as parameter to build it). In this
case, list is just as good as any other foldable for the internal
workings. You can use another foldable if you wish, but you need to
use some foldable, because Foldable itself is only a behavioural
definition that cannot be used directly. Thus, what I personally said
about efficiency was in the case that you wanted the user to be able
to *specify as an argument* what instance of Foldable to use for this.
If you don't care about efficiency, then use lists, or any other
foldable of your choice.
Let me see if I can make this clearer with an analogy. You go to a
workshop and ask them to build a metal bar for you. You say: it needs
to be this size, this weight and be able to resist this amount of
strength (that would be equivalent to the typeclass, it needs to be
Foldable). Now, what would break the transparency that typeclasses and
genericity provide would be if they asked you: "what are you going to
use this metal bar for?". They don't need to know, as long as they
produce a metal bar that fulfills your requirements. So far so good.
But now, imagine that you asked them: "I want you to build the metal
bar in such a way that it is independent of the tools that you have
available". They would be puzzled. Why do you care what tools they use
to build the metal bar? You want a metal bar with a set of
characteristics, you will get it. How they build the metal bar and how
specific that building of the metal bar may be is absolutely
irrelevant to you. This is the list. The list (or any other foldable
that you wish to use), is just the tool that you use to check for
duplicity. It is *not* the output result of your function. So using it
does not break genericity in any way.
The second, slightly less important point, is about the type
signatures. You want GHC to derive the signatures on its own? Fine.
Take the code that I provided you, and remove the type signatures. It
compiles, it works, and it infers exactly the same type signatures
that I provided. There are two reasons for which I think your approach
that "it is better if I don't specify the type signatures" is mistaken.
First, the reason you want to provide type signatures is because it
makes the code clearer. Saying that "GHC should derive the type
signatures" is a bit like writing a mono-function program and saying
"the compiler should not care about how long my functions are". Type
signatures help the programmer understand what the functions do, help
you program by making it easier to see if you can use a function or
not by looking at its type signature, and make it easier to debug by
modularizing the problems.
Second, depending on what extensions you use (and you are using
RankNTypes and KindSignatures, which are not trivial extensions), type
signatures on functions or type annotations might not be avoidable,
precisely because of ambiguity. In this particular case, they can be
removed, as I said, but there are some programs that are inevitably
ambiguous unless you explicitly specify the types. And this is not a
GHC limitation, it is a mathematical limitation of the programming
model, so type signatures are not optional sometimes.
But, as I said, if you really disagree and prefer not to provide type
signatures, then don't. The code I provided still works perfectly, and
the reason why using lists internally does not break genericity still
holds regardless of that.
Quoting Dušan Kolář <kolar at fit.vut.cz> on Wed, 07 Aug 2019 14:38:12 +0200:
> Thanks all for the answers, and no, they are not what I was asking for...
> Not providing type signatures, yes, no type signatures provided, GHC
> should derive
> them on its own. My question was, why it is not able to do that and
> how force GHC
> to do that. Without extra type info...
> The original type signature was simple: chkDup :: (Eq a, Num a) =>
> [a] -> Bool
> I would be quite happy to have something similar, just for  to
> have some generic
> type - auto-magically :-)
> And no, my intention was not to make it a bit faster for larger
> inputs, just make
> clear and clean code without extra type signatures, easy to read and
> simple to
> understand. Real-life input has 36 six members at most.
> So thank you once again, unfortunately, my conclusion is that
> writing generic code
> is not always beneficial - neither for reading nor for generality...
> Thank you once again,
The University of Edinburgh is a charitable body, registered in
Scotland, with registration number SC005336.
More information about the Haskell-Cafe