Ale*_*ing 6 haskell typeclass ghc
假设我有一些类型类:
data Foo = Foo deriving (Show)
class Monad m => MonadFoo m where
getFoo :: m Foo
Run Code Online (Sandbox Code Playgroud)
由于GHC通过字典传递(SPECIALIZE
尽管使用了)来实现类型类,因此它有效地转换getFoo
为类似下面的内容:
data MonadFooDict m = MonadFooDict { getFoo :: m Foo }
Run Code Online (Sandbox Code Playgroud)
...并且在调用开头时插入一个额外的参数来getFoo
围绕字典.
有时,我可能想要动态选择一个实例,因此自己传递一个字典可能是可取的.我可以通过创建一个将为我编写字典的实例来自己模拟这个.
newtype DynamicMonadFoo a = DynamicMonadFoo
{ runFoo :: MonadFooDict DynamicMonadFoo -> a }
deriving ( Functor, Applicative, Monad
, MonadReader (MonadFooDict DynamicMonadFoo) )
instance MonadFoo DynamicMonadFoo where
getFoo = join $ asks _getFoo
Run Code Online (Sandbox Code Playgroud)
现在,给定一些带MonadFoo
约束的runFoo
函数,我可以使用该函数向它传递一个显式的类型类字典:
showCurrentFoo :: MonadFoo m => m String
showCurrentFoo = do
foo <- getFoo
return ("current foo: " ++ show foo)
ghci> runFoo showCurrentFoo MonadFooDict { _getFoo = return Foo }
"current foo: Foo"
Run Code Online (Sandbox Code Playgroud)
这真的很酷,但似乎这样一个简单的任务,GHC可能会在没有所有样板的情况下暴露某种类型的库(理想情况下,这种方式可以更好地处理非monadic类型类).鉴于GHC具有一些"反射式"功能Data.Typeable
,这似乎不属于可能性范围,但我不确定它是否确实以某种形式存在.
任何现有的内置插件或其他库是否允许更自动地执行此操作?
在哈斯克尔学院有一篇关于此的文章: