Hi, This is one of those topics everybody else seems to be familiar with, but which I don't quite understand, and can't seem to find any good information about. I have a function declared as: anova2 :: (Fractional c, Ord b) => [a->b] -> (a->c) -> [a] -> [Anova1 c] where the first parameter is a list of classifiers. I could simplify it, I guess, to something like classify :: Eq b => [a->b] -> [a] -> [[[a]]] classify cs xs = ... where for each classifying function in cs, I would get the xs partitioned accordingly. E.g. classify [fst,snd] [(1,0), (1,2), (2,0)] would yield [ [(1,0), (1,2)], [(2,0)] -- classified by `fst` , [(1,0), (2,0)], [(1,2)]] -- classified by `snd` Now, obviously, the problem is that fst and snd, being passed in a list, needs to be of the same type; this complicates classifying a list of type [(Int,Bool)], for instance¹. I have a vague notion this is solvable using quantifiers (since I ever only use Eq operations on the type), but I'm not sure exactly how, I can't seem to find a good tutorial, and my Monte-Carlo programming approach doesn't seem to be leading anywhere :-) Can somebody suggest a solution, or a place to look? -kzm ¹ I guess I can convert Bool to Int (True->1, False->0), but it's not very appealing, IMHO. -- If I haven't seen further, it is by standing in the footprints of giants
I don't properly understand this either, but as it happens I was looking at this in the GHC user guide only yesterday... [[ : MkFoo :: forall a. a -> (a -> Bool) -> Foo Nil :: Foo Notice that the type variable a in the type of MkFoo does not appear in the data type itself, which is plain Foo. For example, the following expression is fine: [MkFoo 3 even, MkFoo 'c' isUpper] :: [Foo] Here, (MkFoo 3 even) packages an integer with a function even that maps an integer to Bool; and MkFoo 'c' isUpper packages a character with a compatible function. These two things are each of type Foo and can be put in a list. : ]] -- http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html... At 15:20 04/06/03 +0200, Ketil Z. Malde wrote:
Hi,
This is one of those topics everybody else seems to be familiar with, but which I don't quite understand, and can't seem to find any good information about.
I have a function declared as:
anova2 :: (Fractional c, Ord b) => [a->b] -> (a->c) -> [a] -> [Anova1 c]
where the first parameter is a list of classifiers. I could simplify it, I guess, to something like
classify :: Eq b => [a->b] -> [a] -> [[[a]]] classify cs xs = ...
where for each classifying function in cs, I would get the xs partitioned accordingly. E.g.
classify [fst,snd] [(1,0), (1,2), (2,0)]
would yield
[ [(1,0), (1,2)], [(2,0)] -- classified by `fst` , [(1,0), (2,0)], [(1,2)]] -- classified by `snd`
Now, obviously, the problem is that fst and snd, being passed in a list, needs to be of the same type; this complicates classifying a list of type [(Int,Bool)], for instance¹.
I have a vague notion this is solvable using quantifiers (since I ever only use Eq operations on the type), but I'm not sure exactly how, I can't seem to find a good tutorial, and my Monte-Carlo programming approach doesn't seem to be leading anywhere :-)
Can somebody suggest a solution, or a place to look?
-kzm
¹ I guess I can convert Bool to Int (True->1, False->0), but it's not very appealing, IMHO. -- If I haven't seen further, it is by standing in the footprints of giants _______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
------------------- Graham Klyne <GK@NineByNine.org> PGP: 0FAA 69FF C083 000B A2E9 A131 01B9 1C7A DBCA CB5E
Ketil Z. Malde wrote:
I have a function declared as:
anova2 :: (Fractional c, Ord b) => [a->b] -> (a->c) -> [a] -> [Anova1 c]
where the first parameter is a list of classifiers. I could simplify it, I guess, to something like
classify :: Eq b => [a->b] -> [a] -> [[[a]]]
^^^ Isn't this one list too many?
classify cs xs = ...
where for each classifying function in cs, I would get the xs partitioned accordingly. E.g.
classify [fst,snd] [(1,0), (1,2), (2,0)]
would yield
[ [(1,0), (1,2)], [(2,0)] -- classified by `fst` , [(1,0), (2,0)], [(1,2)]] -- classified by `snd`
Now, obviously, the problem is that fst and snd, being passed in a list, needs to be of the same type; this complicates classifying a list of type [(Int,Bool)], for instance?.
What you'd need would be an existential type of the form classify :: [exists b. Eq b => a->b] -> [a] -> [[a]] Such a type is not available directly in Haskell, but only through an auxilary data type: data Classifier a = forall b. Eq b => Classifier (a -> b) Using that you should be able to implement classify :: [Classifier a] -> [a] -> [[a]] Cheers, - Andreas -- Andreas Rossberg, rossberg@ps.uni-sb.de "Computer games don't affect kids; I mean if Pac Man affected us as kids, we would all be running around in darkened rooms, munching magic pills, and listening to repetitive electronic music." - Kristian Wilson, Nintendo Inc.
Ketil Z. Malde writes: : | classify :: Eq b => [a->b] -> [a] -> [[[a]]] | classify cs xs = ... | | where for each classifying function in cs, I would get the xs | partitioned accordingly. E.g. | | classify [fst,snd] [(1,0), (1,2), (2,0)] | | would yield | | [ [(1,0), (1,2)], [(2,0)] -- classified by `fst` | , [(1,0), (2,0)], [(1,2)]] -- classified by `snd` | | Now, obviously, the problem is that fst and snd, being passed in a | list, needs to be of the same type; this complicates classifying a | list of type [(Int,Bool)], for instance¹. : | Can somebody suggest a solution, or a place to look? Hi. Another way is to extend the role of the classifying functions, so that they go on to make the comparison after extracting the classification keys. Here's a naive implementation.
import Data.List(partition)
classifyBy :: (a -> a -> Bool) -> [a] -> [[a]] classifyBy eq [] = [] classifyBy eq (x:xs) = case partition (eq x) xs of (ys, zs) -> (x:ys):classifyBy eq zs
classifyBys :: [a -> a -> Bool] -> [a] -> [[[a]]] classifyBys eqs xs = [classifyBy eq xs | eq <- eqs]
fsteq x y = fst x == fst y sndeq x y = snd x == snd y
test = classifyBys [fsteq, sndeq] [(1, '0'), (1, '2'), (2, '0')]
In practice, you'd probably want an Ord-like comparison (a -> a -> Ordering) instead of the Eq-like one (a -> a -> Bool). Regards, Tom 'existential quantifier skeptic' ;-)
participants (4)
-
Andreas Rossberg -
Graham Klyne -
ketil@ii.uib.no -
Tom Pledger