On Thursday 05 July 2007, Andrew Coppin wrote: > Jonathan Cast wrote: > > On Thursday 05 July 2007, Andrew Coppin wrote: > >> ...OK, anybody have a solution that works in Haskell 98? > > > > Rank-2 types are perhaps /the/ most common, widely accepted extension to > > Haskell 98, after the approved addendum for FFI and the draft addendum > > for hierarchical modules. I would really be concerned about using them > > (it's certainly not like they're going to just disappear on you one day, > > like say functional dependencies almost certainly will). But that's just > > me. > > Personally, I just try to avoid *all* language extensions - mainly > because most of them are utterly incomprehensible.
Ah, there's your problem :) > (But then, perhaps > that's just because they all cover extremely rare edge cases?) I wouldn't call rank-2 types extremely rare . . . <snip> > >> So *neeer* :-P > > > > My first thought is that surely you must have said > > > > newtype Parser state x y > > = forall src. Source src => Parser ((state, src x) -> (state, src x, > > y)) > > > > when you meant > > > > newtype Parser state x y > > = Parser (forall src. Source src => (state, src x) -> (state, src x, > > y)) > > > > The relative order of the constructor name and the forall is very > > important! > > Care to explain what's different about these apparently identical > declarations? Sure. Given newtype Parser0 state x y = forall src. Source src => Parser0 ((state, src x) -> (state, src x, y)) we get Parser0 :: forall src. Source src => ((state, src x) -> (state, src x, y)) -> Parser0 state x y which type assignment is isomorphic to (note: not legal Haskell!) Parser0 :: (exists src. Source src => (state, src x) -> (state, src x, y)) -> Parser0 state x y Given newtype Parser1 state x y = Parser1 (forall src. Source src => (state, src x) -> (state, src x, y)) we get Parser1 :: (forall src. Source src => (state, src x) -> (state, src x, y)) -> Parser state x y The key difference is in the quantifier in the type of the constructor's argument. The exists quantifier (on types) is a tupling operator; Parser0 takes three arguments: a type (elided at run time!), an instance for the Source class (not elided at run time!), and a function implementing the parser. The forall quantifier is a function-forming operator; Parser1 takes one argument, which is a function on a type (elided at run time!) and an instance for the Source class (not elided at run time!), yielding a function implementing the parser. Using a (thoroughly invalid Haskell) record syntax, we could write the two versions Parser0 :: { type src :: *, dict :: Source src, fun :: (state, src x) -> (state, src x, y)} -> Parser0 state x y Parser1 :: ({ type src :: *, dict :: Source src, input :: (state, src x)} -> (state, src x, y)) -> Parser1 state x y which may make the distinction a bit clearer (or not). Jonathan Cast http://sourceforge.net/projects/fid-core http://sourceforge.net/projects/fid-emacs _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe