functional dependencies question
Hi, My understanding of functional dependencies is that they can be used to ensure that one type depends on another type. For example, the type of location depends could on the type of the object at that location. Consider two models 1) The location of an aircraft landing should have location of the type AirportCode, 2) The location of a car's destination should have a type CartesianCoordinate. AirportCodes should not be used as locations in 2) and CartesianCoordinates should not be used as locations in 1). Haskell class, instances, and fundeps were used to represent the above requirements. I generalized the requirement a bit, testing on a variety of types (below). Obviously, some cases are ambigous and/or conflicting and the Haskell compiler correctly flags this. Why do some cases such as 1) fail to run even if they are the only instantiation. Regards, Pat {- C:\GHC\ghc-6.8.3\bin\ghci.exe -XMultiParamTypeClasses -XFunctionalDependencies -fglasgow-exts -fallow-undecidable-instances -} class LocatedAt object location | object -> location where spatialLocation :: object -> location -- 1) Compiles but does not run instance LocatedAt Int String where spatialLocation(1)="home" -- 2) Compiles and runs OK instance LocatedAt String Int where spatialLocation("home")=1 -- 3) Compiles and runs OK, but obviously not in conjunction with 2 instance LocatedAt String String where spatialLocation("home")="home" -- 4) Compiles and runs OK instance LocatedAt Bool String where spatialLocation(True)="home" -- 5) Compiles and runs OK, but obviously not in conjunction with 2 instance LocatedAt String Bool where spatialLocation("home") = True -- 6) Not OK instance LocatedAt Float String where spatialLocation(2.3)="home" -- 7) Compiles but does not run instance LocatedAt Int Char where spatialLocation(1)='1' -- 8) Compiles and runs OK instance LocatedAt Char Int where spatialLocation('1')=1 This message has been scanned for content and viruses by the DIT Information Services E-Mail Scanning Service, and is believed to be clean. http://www.dit.ie
On 01/07/10 12:37, Patrick Browne wrote:
Why do some cases such as 1) fail to run even if they are the only instantiation.
-- 1) Compiles but does not run instance LocatedAt Int String where spatialLocation(1)="home"
That instance is fine. I presume the problem is that you are trying to run this function using "spatialLocation 1" as the function call. The problem with that is that the "1" part has type Num a => a, i.e. it can be any Num type. Even though you only have one instance, that's not used to constrain the type for "1". The call "spatialLocation (1::Int)" works correctly. Looking at your other examples, all the ones that don't work have a numeric type for the parameter, so I suspect it is the same issue throughout. Thanks, Neil.
Neil, Does the following sum up the situation? The class Num has subclasses containing various numeric types and the literal 1 is a value for one or more of those types. Hence the Haskell compiler says the instance 1) is OK. But at run time, without the quantified (1:Int), the 1 could of more than one type, which causes a problem. Thanks for the quick and informative response, Pat Neil Brown wrote:
On 01/07/10 12:37, Patrick Browne wrote:
Why do some cases such as 1) fail to run even if they are the only instantiation.
-- 1) Compiles but does not run instance LocatedAt Int String where spatialLocation(1)="home"
That instance is fine. I presume the problem is that you are trying to run this function using "spatialLocation 1" as the function call. The problem with that is that the "1" part has type Num a => a, i.e. it can be any Num type. Even though you only have one instance, that's not used to constrain the type for "1". The call "spatialLocation (1::Int)" works correctly. Looking at your other examples, all the ones that don't work have a numeric type for the parameter, so I suspect it is the same issue throughout.
Thanks,
Neil.
This message has been scanned for content and viruses by the DIT Information Services E-Mail Scanning Service, and is believed to be clean. http://www.dit.ie
On 01/07/10 13:11, Patrick Browne wrote:
Neil, Does the following sum up the situation? The class Num has subclasses containing various numeric types and the literal 1 is a value for one or more of those types. Hence the Haskell compiler says the instance 1) is OK. But at run time, without the quantified (1:Int), the 1 could of more than one type, which causes a problem.
I think you have the rough gist, but a few clarifications are necessary. I've added some angle brackets to show the differences: The class Num has <instances for> various numeric types and the literal 1 <is a shorthand for fromIntegral 1> which can be instantiated to any of those types. At <compile time>, without the qualified (1::Int), the 1 could be instatianted to any type, and so <the compiler cannot determine which instance is required, because it doesn't know an exact type for the literal 1>. All this is at compile-time, not run-time. The problem comes down to needing to know a specific type in order to pick a type-class instance -- the functional dependencies are actually irrelevant to this aspect. Let's say I have this simpler class: class Big a where isBig :: a -> Bool instance Big Int where isBig x = (x > 1000000) -- big for an Int instance Big Integer where isBig x = (x > 1000000000000) -- big for an Integer If you ask "isBig 99999999", the compiler needs to know which instance to use. The literal 99999999 can be an Int or an Integer, so the instance is ambigious, and that will cause the error. So the compiler needs some clarification to choose an instance. Thanks, Neil.
Patrick Browne <patrick.browne@dit.ie> writes:
Why do some cases such as 1) fail to run even if they are the only instantiation.
I think this is because literal numbers are polymorphic, i.e. a '1' in your source code is shorthand for 'fromIntegral 1', which is a type of Num a => a. Thus, 'spatialLocation 1' doesn't tell the compiler enough to know that you don't want the Float instance, for instance. Try 'spatialLocation (1::Int)'? Similar for floating point literals, they are of type Fractional a => a. -k -- If I haven't seen further, it is by standing in the footprints of giants
participants (4)
-
Ketil Malde -
Miguel Mitrofanov -
Neil Brown -
Patrick Browne