Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to syntactically simulate empty constraints with GHC < 7.8.1?

Tags:

types

haskell

ghc

TL;DR

Is there a way to simulate empty constraints with GHC < 7.8.1? Something similar to

{-# LANGUAGE NullaryTypeClasses #-}
class HasCallStack
instance HasCallStack

so that e.g.

foo :: HasCallStack => Int -> Int

is technically the same as

foo :: Int -> Int

Motivation

GHC 8.0.1 introduces HasCallStack as:

HasCallStack = (?callStack :: CallStack)

For a compatibility shim I want to define HasCallStack for all versions of GHC back to 7.0.1.

For versions of GHC that have support for implicit parameter based call stacks, HasCallStack should be functionally equivalent to what we have in GHC 8.0.1.

For versions of GHC that lack support for implicit parameter based call stacks (that is all versions of GHC < 7.10.2), HasCallStack should be functionally equivalent to the empty constraint.

For completeness, here is the code that we could use if we only care about GHC 7.8.1 and later:

#if MIN_VERSION_base(4,8,1)
type HasCallStack = (?callStack :: CallStack)
#else
class HasCallStack
instance HasCallStack
#endif

Is there a way to make this work for older versions of GHC?

For reference, I'll add my current solution as an answer. But I'd love to get input on other ways to tackle this.

like image 791
Simon Hengel Avatar asked Dec 19 '25 05:12

Simon Hengel


1 Answers

I don't know of any way to support the exact same syntax we have in GHC 8.0.1. However, it's possible to optionally add a constraint by using a type synonym and Rank2Types. The following code works for all versions of GHC back to 7.0.1.

#if MIN_VERSION_base(4,8,1)
type HasCallStack a = (?callStack :: CallStack) => a
#else
type HasCallStack a = a
#endif

The example from your question

foo :: HasCallStack => Int -> Int

becomes

foo :: HasCallStack(Int -> Int)

Note that this is quite robust. I haven't encountered any situation where this would not work, it e.g. even works when foo has other constraints or when foo is a class method.

like image 75
Simon Hengel Avatar answered Dec 21 '25 00:12

Simon Hengel