[Haskell-cafe] Inferred type is not general enough

Glynn Clements glynn.clements at virgin.net
Thu Jul 8 05:04:47 EDT 2004

Ivan Tihonov wrote:

> I start some ip networks related work in haskell and wrote two basic 
> classes Location and Packet. Before writing IpLocation and IpPacket 
> instances i have written simple TestLocation and TestPacket instances 
> just to compile this and check for errors in class definitions. But 
> looks like i misunderstand some haskell principles...
> ======================================================
> class Location a where
>          point :: a -> String
> class Packet a where
>          source, destination :: Location b => a -> b

This says that source can return any type which is an instance of
Location. IOW, any instance of Packet can have any instance of
Location as its source and destination (and can even use different
instances of Location for the two functions).

> data TestLocation = TestSource | TestDestination
> data TestPacket = TestPacket

> instance Packet TestPacket where
>          source p = TestSource

However, this definition of source has type:

	TestPacket -> TestLocation

when, according to the class definition, it should have type:

	(Location b) => TestPacket -> b

> ERROR Test.hs:20 - Inferred type is not general enough
> *** Expression    : source
> *** Expected type : (Packet TestPacket, Location a) => TestPacket -> a
> *** Inferred type : (Packet TestPacket, Location TestLocation) => TestPacket -> TestLocation

Hence this error message; the function returns a specific instance of
Location, when it should return an arbitry instance.

You can use functional dependencies, which aren't in the Haskell98
standard, but are supported by Hugs (use the -98 switch to enable
extensions) and GHC (use the -fglasgow-exts switch). I.e.:

	class (Location b)  => Packet a b | a -> b where
	         source, destination :: a -> b
	         size :: Num c => a -> c
	instance Packet TestPacket TestLocation where

The class definition says that each instance of Packet uses a specific
instance of Location. The instance declaration says that, for
TestPacket, source and destination will always have type TestLocation.

Glynn Clements <glynn.clements at virgin.net>

More information about the Haskell-Cafe mailing list