Can a fundep force parametricity

I would like to make a two-parameter type class where some choices of the first type uniquely determine the second type, and other choices of the first type promise to work with any choice of the second type. This code seems a bit suspicious, but is accepted thanks to UndecidableInstances.
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, UndecidableInstances #-}
class C a b | a -> b where update :: b -> a -> a
instance C (Maybe a) a where update x m = fmap (const x) m
instance C Int b where update _ n = n
The application is a program transformation problem, where I'm using distinct types for Statements, Expressions, etc, but want a single environment that contains the bindings for variables of each different type for implementing rewriting rules. I'm trying to make a type class for binding things in the environment. Some of the terms, such as Statement, have a type parameter for semantic analysis information, so the Environment type has the type parameter as well. Then the instance a statement variable needs to require that the info type of the statement matches that of the environment, but the operation for binding an expression should be polymorphic in the info type of the environment. I usually have enough type information around that type checking succeeds without the fundep, so it's not currently a big problem. Brandon

On Tuesday 02 November 2010 4:01:33 pm Brandon Moore wrote:
instance C Int b where
update _ n = n
This instance violates the fundep. The fundep says that the first parameter determines the second. However, this instance is a scheme for declaring infinitely many monomorphic instances, like: C Int Int C Int Char C Int () ... Which means that the first argument doesn't determine the second in the case of Int. I don't really know why undecidable instances allows this. I suppose it's conceivable that you could have an instance: instance D x => C Int x where the constraint on x ensures that it is unique, despite that not being checkable. In general, though, instances like these would be unsound, except that fundeps don't refine types eagerly enough to cause that. You can certainly imagine, though, that the fact that there are instances: C Int Int C Int Char and the fact that the first argument to C determines the second would allow us to conclude that Int = Char. -- Dan
participants (2)
-
Brandon Moore
-
Dan Doel