Is there a way to specify the recursive behaviour of implicit parameters while still writing a type signature?

Viewed 91

According to the GHC User’s Guide, explicitly bound implicit parameters are only propagated into recursive calls if the function has a type signature, and otherwise, the implicit parameters from the original call are used.

fu True = ?gn
fu False = let ?gn = not ?gn in fu True
br :: (?sp :: Bool) => Bool -> Bool
br True = ?sp
br False = let ?sp = not ?sp in br True
ghci> let ?gn = True in fu False
True
ghci> let ?sp = True in br False
False

However, what if I want to provide a type signature to fu while retaining its behaviour? Can I do that?

1 Answers

You can do a "worker-wrapper" transformation: take the recursive part of the function and move it into a local binding. This lets you make the implicit parameters explicit, so the recursive call has no ambiguity.

fu :: (?gn :: Bool) => Bool -> Bool
fu = go ?gn
    where
        go gn True = gn
        go gn False = go (not gn) True

I personally find this version easier to understand anyway.

Related