Converting Functional Dependency class to Type Family instances

萝らか妹 提交于 2019-12-05 22:43:34
Benjamin Hodgson

Don't overthink it.

class C a b | a -> b
instance C T U

roughly translates into

class C' a where
    type B a
instance C' T where
    type B T = U

They're semantically somewhat different, even though they behave in a similar way. C is a two-parameter class, but its second parameter is uniquely determined by its first. C' is a one-parameter class with an associated type. Associated types are interpreted as top-level axioms for FC's coercion system whereas fundeps basically just affect unification.

It is possible to convert between the two styles, but you have to use a newtype to bind the variables in the type equation.

newtype WrappedB a = WrappedB { unwrapB :: B a }
instance C' a => C a (WrappedB a)  -- you can't use a type synonym family in an instance

newtype Wrap a b = Wrap { unWrap :: a }
instance C a b => C' (Wrap a b) where
    type B (Wrap a b) = b  -- b needs to be bound on the LHS of this equation

In general I don't advise writing the sort of generic instance you've attempted in your question, because such instances have a tendency to be overlapping.

Functional dependencies are less, um, weird than type families, though. All other things being equal I tend to prefer a fundep.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!