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

jbe*_*man 5 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 )
Run Code Online (Sandbox Code Playgroud)

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

  1. Wrapped类型构造不出口

  2. 用户将始终调用绑定中的unwrap所有Wrapped数据(因为我的应用程序的枯燥细节),所以在实践中不应该有歧义

这个共识似乎UndecidableInstances并不是很糟糕,但我希望在继续之前确保上述内容是犹太人的.


更新w /解决方案

我对此感到困惑,但我能够通过以下方式解决我的问题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)
Run Code Online (Sandbox Code Playgroud)

Dan*_*her 10

采用UndecidableInstances单是一般洁净,什么UndecidableInstances做是允许的类型检查,以尝试解决情况时,它不能提前证明它可以完成.如果确实如此,那么代码的安全性可能比提前证明终止的安全性要差.

然而,你的情况,你可以创建一种情况:将型循环检查与导致约束的表达WrapDecomp x (x,y),例如

foo x = [fst $ decomp x, x]
Run Code Online (Sandbox Code Playgroud)

使用fst需要decomp x有类型(a,b)对于某些类型的ab,从而一个instance WrapDecomp t (a,b)其中t是的类型x.在同一个列表中要求也x有磁带a,所以

instance WrapDecomp a (a,b)
Run Code Online (Sandbox Code Playgroud)

第二个参数的唯一实例是

instance (Wrapdecomp x x', WrapDecomp y y') => WrapDecomp (x,y) (x',y')
Run Code Online (Sandbox Code Playgroud)

因此a = (x,y)对于某些类型x而且y约束foo变为

WrapDecomp (x,y) ((x,y),b)
Run Code Online (Sandbox Code Playgroud)

对实例说如果有实例则存在这样的实例

WrapDecomp y b
Run Code Online (Sandbox Code Playgroud)

WrapDecomp x (x,y)
Run Code Online (Sandbox Code Playgroud)

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