When using -XOverloadedStrings
you can implement IsString
which only requires a function fromString
.
Now if you want to use string literals for pattern matching, you also have to implement Eq
, which makes sense:
f :: MyString -> Bool
f "foo" = True
f _ = False
-- equivalent to
f x
| x == fromString "foo" = True
| otherwise = False
But then why does the IsList
type class which is used with -XOverloadedLists
require that you implement toList
?
In the wiki the only mentioned use-case of toList
is pattern matching.
And I get that Eq
is not sufficient for list pattern matching.
But then toList
should be in a different type class that's only required if you'd like to use list pattern matching with your type, just like IsString
does not require Eq
.
The annoying thing about this to me is that the condition fromList . toList = id
has to be met but this simply can't be guaranteed for some types like e.g. an unordered collection which make no guarantees that the order of elements is kept.
This just seems very inconsistent.
What is overloaded in both extensions is merely a notation. The difference between the two notations is that a list can contain variables (
[x, y]
) while strings cannot: Haskell doesn't do variable interpolation likelet x = "apple" in "I like {x} pie")
This difference becomes important when I use either notation inside a pattern: I expect to be able to bind variables in a pattern like
... while, even though I can use string literals as a pattern
... those will never bind a variable
To see the difference this makes, suppose that
-XOverloadedLists
would translate pattern matches exactly like-XOverloadedStrings
. The pattern matchwould be translated as
But
fromList [x, y]
is not a constructor pattern: for a givenz
, there may be several different values forx
andy
such thatfromList [x, y] == z
(In your example, an unordered collection{1, 2}
is equal tofromList [1, 2]
but also tofromList [2, 1]
- so should the result off {1, 2}
beTrue
orFalse
?This shows that for pattern matching to work,
Mylist a
needs to be isomorphic to[a]
, in other words, atoList
is needed that satisfies the appropriate laws. We then can find the uniquex, y
such thatz == fromList [x, y]
by applyingtoList
toz
, so the translation instead isOr, with a view pattern (which doesn't even need
Eq
anymore):So, ultimately, your
IsList
class without thetoList
would not allow overloaded list patterns, but still make it possible to denote your unordered collection{1, 2}
using list notation[1, 2]
. But then we would have-XOverloadedLists
and-XOverloadedListPatterns
- probably not worth the hassle.