且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何解决“非法数据类型上下文” (使用-XDatatypeContexts)?

更新时间:2022-11-20 21:53:27

Typeclass contexts in datatypes are now regarded as a not so useful feature. The problem is that the following does not compile:

foo :: Units a -> a
foo (Units x _) = x+x

This intuitively should compile, since the Units a argument can only be constructed for a type a satisfying Num a. So, on destruction (pattern matching) one should be able to access the Num a instance. However this is not the case, and a Num a must be counterintuitively provided on destruction as well:

foo :: Num a => Units a -> a
foo (Units x _) = x+x

The standard suggestion is therefore to remove the constraint Num a from the Units a datatype declaration, and add it instead to every function involving Units a.

Another option is to enable GADTs and change the datatype to:

data Units a where
   Units :: Num a => a -> SymbolicManip a -> Units a

This does the "right" thing: a Num a instance is required to construct a value, and is instead provided on destruction. In this way, the first foo declaration above will be well-typed.


I almost forgot the "quick & dirty" option, which is to enable the obsolescent datatype context feature: this is done by adding at the beginning of your file the line

{-# LANGUAGE DatatypeContexts #-}

Still, I would rather modify the code than to enable this language extension.