这是UndecidableInstances的使用吗?备择方案?

时间:2012-08-04 19:02:37

标签: haskell types ghc type-families

我想在库中做一些魔术,允许产品类型以多态方式进行解构。这是一个或多或少的工作模型,说明了我想做的事情:

{-# 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 )

我的实际应用程序是一个库,并且有两个属性可以使上面提到的我注意到

  1. 未导出Wrapped类型构造函数

  2. 用户将始终在绑定中的所有unwrap数据上调用Wrapped(因为我的应用程序的细节很无聊),所以在练习中不应该有歧义

  3. 共识似乎是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)
    

1 个答案:

答案 0 :(得分:10)

一般来说UndecidableInstances单独使用是犹太的,UndecidableInstances所做的是允许类型检查器在事先无法证明它将完成时尝试解析实例。如果确实如此,那么代码的安全性就不如预先证明终止的安全性。

但是,对于您的实例,您可以创建一种情况,其中类型检查器将使用导致约束WrapDecomp x (x,y)的表达式循环,例如

foo x = [fst $ decomp x, x]

使用fst要求decomp x为某些类型(a,b)a添加b类型,因此instance WrapDecomp t (a,b)其中t 1}}是x的类型。列在同一个列表中要求x也有磁带a,所以

instance WrapDecomp a (a,b)

第二个参数配对的唯一实例是

instance (Wrapdecomp x x', WrapDecomp y y') => WrapDecomp (x,y) (x',y')

因此某些类型a = (x,y)x yfoo的约束变为

WrapDecomp (x,y) ((x,y),b)

对实例说如果有实例

就有这样的实例
WrapDecomp y b

WrapDecomp x (x,y)

这是我们开始的实例的确切形式。