monomorphism restriction vs unused

Evan Laforge <[email protected]> Sun, 21 Jun 2026 12:34:59 -0700
Newsgroups gmane.comp.lang.haskell.cafe
Message-ID <CACbaDy4ixxB-yX2OaVgiuuzN_J3r-FXQAi_sTSEPfQ-mAmPo3Q@mail.gmail.com>
I have a little DSL I use from ghci and I finally tracked down a minor
annoyance, which is when I comment out some lines in a definition,
sometimes certain now-unused `where` definitions now become ambiguity
errors.  Here's a minimized repro:

```
{-# LANGUAGE OverloadedStrings #-}
-- {-# LANGUAGE NoMonomorphismRestriction #-}
import Data.String (IsString(..))

data Thing a = Thing

-- 1. IsString instance on concrete type.
instance IsString (Thing ()) where fromString _ = Thing

-- 2. trans is polymorphic
trans :: Thing a -> Thing a
trans = id

-- 3. ambig is a simple binding under the Monomorphism Restriction, and is
-- unused.
ex :: ()
ex = () where unused = trans "k" -- Ambiguous type variable 'a0'
```

In place of `ex` imagine a large expression with many things in
`where`, and part of the expression was temporarily commented out
which just happened to contain the uses of `unused`.

As the comment implies, this is ultimately a monomorphism restriction
thing.  My understanding is that `trans` keeps defaulting from
happening and the restriction then forbids leaving `unused`
polymorphic.  It was confusing to me given that unused is unused, but
I'm guessing the type checking runs before dead code elimination.

So I think this is all working as intended, or rather, an unexpected
interaction between defaulting being a "best effort" heuristic, and
monomorphism restriction doing its thing, and the type checking ->
dead code order, but all 3 things exist for good reasons which are
unlikely to change.

The way around is to turn on NoMonomorphismRestriction, which
unfortunately counts as a flag change and hence causes ghci to not be
able to load .o files... or compile the .o files with that too, but
that of course may lead to unexpected redundant evaluation.

https://www.haskell.org/onlinereport/decls.html#sect4.5.5 talks about
"no way to enforce monomorphic use of an exported binding", but is
this still relevant when it's usual to require type signatures for all
top-level bindings?  Are there still non-toplevel let/where-bound
things which could result in redundant work?
_______________________________________________
Haskell-Cafe mailing list -- [email protected]
To (un)subscribe, modify options or view archives go to:
Only members subscribed via the mailman list are allowed to post.