# Ad-hoc polymorphism erodes type-safety

**URL:** <https://discourse.haskell.org/t/ad-hoc-polymorphism-erodes-type-safety/7464>\
**Category:** Links\
**Created:** [August 29, 2023, 2:28pm UTC](https://discourse.haskell.org/t/ad-hoc-polymorphism-erodes-type-safety/7464 "2023-08-29T14:28:13Z")\
**Posts on this page:** 6\
**Page:** 2

<div class="post-metadata">

**Author:** ![rhendric](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/rhendric/32/2689_2.png) [@rhendric](https://discourse.haskell.org/u/rhendric)\
**Post date:** [September 1, 2023, 8:08pm UTC](https://discourse.haskell.org/t/ad-hoc-polymorphism-erodes-type-safety/7464/23 "2023-09-01T20:08:39Z")

</div>

And this, I suppose, relies on library authors agreeing to write monomorphic `length` outside of their `Foldable` instances and referencing that when implementing `Foldable`, as opposed to implementing it in the instance body?

That’s probably a good idea for other reasons, too, but it is more verbose and not obviously better if you haven’t read any of this.

---

<div class="post-metadata">

**Author:** ![ChShersh](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/chshersh/32/2551_2.png) [@ChShersh](https://discourse.haskell.org/u/ChShersh)\
**Post date:** [September 2, 2023, 11:09am UTC](https://discourse.haskell.org/t/ad-hoc-polymorphism-erodes-type-safety/7464/24 "2023-09-02T11:09:21Z")

</div>

Interestingly, and I just thought about it, how in common popular languages you can write

```haskell
vec.length
array.length
list.length
tree.length

```

Which is exactly the same number of characters as

```haskell
length vec
length array
length list
length tree

```

But you automatically have guarantees that your methods are called for a specific implementation\*. No need to import `length` qualified and worry about such problems with such a common function like `length` at all.

\* unless such `length` is not something like traits in Rust

---

<div class="post-metadata">

**Author:** ![jaror](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/jaror/32/3271_2.png) [@jaror](https://discourse.haskell.org/u/jaror)\
**Post date:** [September 2, 2023, 11:15am UTC](https://discourse.haskell.org/t/ad-hoc-polymorphism-erodes-type-safety/7464/25 "2023-09-02T11:15:32Z")

</div>

I don’t see how you don’t have the exact same problem in those languages, e.g. in Java you could write something like:

```haskell
myFunction(Maybe<List<Int>> list) {
   ... list.length ... // oops
}

```

(assuming that `Maybe` exists and has a `length` field)

---

<div class="post-metadata">

**Author:** ![tomjaguarpaw](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/tomjaguarpaw/32/1230_2.png) [@tomjaguarpaw](https://discourse.haskell.org/u/tomjaguarpaw)\
**Post date:** [September 2, 2023, 11:15am UTC](https://discourse.haskell.org/t/ad-hoc-polymorphism-erodes-type-safety/7464/26 "2023-09-02T11:15:46Z")

</div>

> [@ChShersh](#):
>
> But you automatically have guarantees that your methods are called for a specific implementation

Sure, if you have a guarantee that `vec` _is_ a `Vec`, but the point of the article is that you call `length settingAllowList`, or `settingAllowList.length` if you like, without a guarantee that it’s actually a list. So when the type of `settingAllowList` changes to `Maybe` something then having written `settingAllowList.length` doesn’t help at all.

---

<div class="post-metadata">

**Author:** ![Shakadak](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/shakadak/32/3626_2.png) [@Shakadak](https://discourse.haskell.org/u/Shakadak)\
**Post date:** [September 2, 2023, 1:31pm UTC](https://discourse.haskell.org/t/ad-hoc-polymorphism-erodes-type-safety/7464/27 "2023-09-02T13:31:56Z")

</div>

I think I would link this with type blindness (or boolean blindness, algebraic blindness, I don’t know what term to use). Which seems to be a similar link to the structure-obliviousness from @ChShersh.

For the specific example of the article, if there weren’t explanations surrounding, I’d be hard pressed to understand what the difference between `Nothing` and `Just []` is supposed to be, whereas something like `Anyone` and `Some []` would mean a bit less mental gymnastics. Though an empty list is still weird so a third constructor might be of interest. In that case, a new data type for the specific business need would have the compiler error on the missing implementation for Foldable.

Although I’m only thinking of this because I’ve just been made aware of this problem, and can link it to other problems. And I’m just shifting the monomorphization from the functions to the data.

---

<div class="post-metadata">

**Author:** ![HeinrichApfelmus](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/heinrichapfelmus/32/117_2.png) [@HeinrichApfelmus](https://discourse.haskell.org/u/HeinrichApfelmus)\
**Post date:** [September 2, 2023, 7:09pm UTC](https://discourse.haskell.org/t/ad-hoc-polymorphism-erodes-type-safety/7464/28 "2023-09-02T19:09:16Z")

</div>

> [@michaelpj](#):
>
> I would be interested to know how many people have actually had a bug caused by this (and of those, in how many cases it was exactly that one `Foldable` tuple footgun). I don’t think I ever have.

I had a bug of this kind involving the `Monad` typeclass once. It looked something like this:

Before:

```haskell
foo :: [Bar] → IO ()
foo xs = do
   this xs
   that

```

After refactoring:

```haskell
foo :: [Bar] → IO ()
foo = do
    this'
    that'

```

I was quite surprised to find out that the `IO` action associated with `that'` was never run.

[Previous page](https://discourse.haskell.org/t/ad-hoc-polymorphism-erodes-type-safety/7464.md?page=1)
