TL; DR
有没有一种方法可以用GHC <7.8.1
模拟空约束?东西
相似
{-# LANGUAGE NullaryTypeClasses #-}
class HasCallStack
instance HasCallStack
这样
foo :: HasCallStack => Int -> Int
在技术上与
foo :: Int -> Int
动机
GHC 8.0.1引入
HasCallStack
为:HasCallStack = (?callStack :: CallStack)
对于兼容垫片,我想为所有版本的
HasCallStack
定义GHC返回
7.0.1
。对于支持基于隐式参数调用堆栈的GHC版本,
HasCallStack
在功能上应与GHC 8.0.1中的等效。对于不支持基于隐式参数的调用堆栈的GHC版本
(这是GHC的所有版本<
7.10.2
),HasCallStack
应该在功能上等同于空约束。
为了完整起见,这是仅关注GHC时可以使用的代码
7.8.1
及更高版本:#if MIN_VERSION_base(4,8,1)
type HasCallStack = (?callStack :: CallStack)
#else
class HasCallStack
instance HasCallStack
#endif
有没有办法使此功能适用于旧版本的GHC?
作为参考,我将添加当前的解决方案作为答案。但我很想得到
输入其他解决方法。
最佳答案
我不知道有什么方法可以支持我们在GHC中使用的完全相同的语法8.0.1
。但是,可以选择使用类型来添加约束
同义词和Rank2Types
。以下代码适用于所有版本的GHC
返回7.0.1
。
#if MIN_VERSION_base(4,8,1)
type HasCallStack a = (?callStack :: CallStack) => a
#else
type HasCallStack a = a
#endif
您问题中的例子
foo :: HasCallStack => Int -> Int
变成
foo :: HasCallStack(Int -> Int)
请注意,这非常可靠。我没有遇到任何无法解决的情况,例如甚至当
foo
具有其他约束或foo
是class
方法时,它也可以工作。