【发布时间】:2012-08-02 10:03:08
【问题描述】:
我想在库中做一些魔术,允许以多态方式解构产品类型。这是一个或多或少的工作模型,说明了我想做的事情:
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, UndecidableInstances #-}
newtype Wrapped a = Wrapped { unwrap :: a }
-- our example structure
ex :: (Int, (Int, Int))
ex = (1,(2,3))
class WrapDecomp x y | y -> x where
decomp :: x -> y
instance (WrapDecomp x x', WrapDecomp y y')=> WrapDecomp (x,y) (x',y') where
decomp (x,y) = (decomp x, decomp y)
instance WrapDecomp x (Wrapped x) where
decomp = Wrapped
example = let w = decomp ex
(w0, w1) = decomp ex
(w0', (w1', w2')) = decomp ex :: (Wrapped Int, (Wrapped Int, Wrapped Int))
in print $ ( unwrap w, unwrap w0, unwrap $ snd w1, unwrap $ fst w1 )
-- Also works:
-- in print $ ( unwrap w, unwrap w0, unwrap w1 )
我的实际应用程序是一个库,并且将具有两个属性,使上述我注意到中的疣可以接受:
Wrapped类型构造函数未导出用户将始终在绑定中的所有
Wrapped数据上调用unwrap(因为我的应用程序的细节很无聊),因此在实践中不应有歧义
大家的共识似乎是 UndecidableInstances 还不错,但我想在继续之前确定以上内容是否符合犹太教规。
更新解决方案
我对此感到困惑,但我能够通过TypeFamilies 解决我的问题,如下所示:
{-# LANGUAGE TypeFamilies #-}
class Out a where
type In a :: *
decomp :: In a -> a
instance Out (Wrapped a) where
type In (Wrapped a) = a
decomp = Wrapped
instance (Out a, Out b)=> Out (a,b) where
type In (a,b) = (In a,In b)
decomp (x,y) = (decomp x, decomp y)
【问题讨论】:
-
我不知道您是否注意到与
newtypepackage 中的类型类“Newtype”的相似之处您的包装物品对实例与库似乎预期的任何东西都不同. -
以前没听说过这个包,谢谢!不过,我不确定这对我有帮助。
-
@jberryman 我错了。您可以使用使类型检查器循环的那些实例编写表达式。然而,这仍然是正确的:上下文堆栈阻止类型检查器实际循环,并且编译的代码(即没有导致循环的表达式)是安全的。
-
@DanielFischer IYI 我想出了一个使用
TypeFamilies的解决方案并在上面进行了编辑。感谢您帮助我了解UndecidableInstances。
标签: haskell types ghc type-families