[Haskell-cafe] Re: Type classes
Forget it. It's more clear reading further. Sorry for the noise. On Sat, Dec 27, 2008 at 1:02 AM, Oscar Picasso wrote: > From Real World Haskell: > > data JValue = JString String > | JNumber Double > | JBool Bool > | JNull > | JObject [(String, JValue)] > | JArray [JValue] > deriving (Eq, Ord, Show) > > > type JSONError = String > > class JSON a where > toJValue :: a -> JValue > fromJValue :: JValue -> Either JSONError a > > instance JSON JValue where > toJValue = id -- Really ? > fromJValue = Right > > Now, instead of applying a constructor like JNumber to a value to wrap it, >> we apply the toJValue function. If we change a value's type, the compiler >> will choose a suitable implementation of toJValue to use with it. > > > Actually it does not work. And I don't see how it could with this toJValue > implementation. Is it possible to make it work by providing another > implementation? > > Oscar > ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Type classes question
Ryan Ingram gmail.com> writes: > [...] > > Here's another possible solution: > > > newtype AsFunctor s a = AF { fstream :: (s a) } > > instance (Stream f) => Functor (AsFunctor f) where > > fmap f (AF s) = AF (fmapStreamDefault f s) > > Now to use fmap you wrap in AF and unwrap with fstream. > > None of the existing solutions are really satisfactory, unfortunately. Bulat Ziganshin gmail.com> writes: > http://haskell.org/haskellwiki/OOP_vs_type_classes may be useful Many thanks to you both for the clarification and pointers. cheers, Roly ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: type classes
> class RingTy a b where > order :: a -> Integer > units :: a -> [b] > class VectorSpaceTy a b | a - > b where > dimension :: a -> Integer > basis :: (Field c) => a -> [b c] > > where `b' is a vector space over the field `c'. It looks like you are using the first (of two) type arguments to the RingTy and VectorSpaceTy type classes as abstract types; in other words, operations on rings and vector spaces don't really care what the type "a" is in "RingTy a b" and "VectorSpaceTy a b". Is that true? Assuming so, if I may strip away the (extremely sweet) syntactic sugar afforded by type classes for a moment, what you seem to be doing is to pass dictionaries of types data RingTy a b = RingTy { order :: a -> Integer, units :: a -> [b] } data VectorSpaceTy a b = VectorSpaceTy { dimension :: a -> Integer, basis :: forall c. (Field c) => a -> [b c] } to operations on rings and vector spaces. Because the type "a" is abstract, you may as well pass dictionaries of types data RingTy b = RingTy { order :: Integer, units :: [b] } data VectorSpaceTy b = VectorSpaceTy { dimension :: Integer, basis :: forall c. (Field c) => [b c] } to these operations. The information that you want computed just once per ring or per vector space can be defined as lexically scoped variables where you create these dictionaries in the first place. To add back the syntactic sugar (i.e., to make the dictionary arguments implicit) and to make the type system check that elements of different vector spaces are not confused, you may find Dylan Thurston's technique useful: http://www.cs.rutgers.edu/~ccshan/prepose/prepose.pdf -- Edit this signature at http://www.digitas.harvard.edu/cgi-bin/ken/sig 2008-07-04 Independence from America! http://caab.org.uk/ 2008-07-05 International Co-operative Day http://ica.coop/ http://www.guardian.co.uk/politics/2008/jul/02/labour.tradeunions ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: type classes
A number of operations -- like order above -- are conceptually connected not to the elements but to the structures themselves. Here is the outline of a more complicated example. I also have a vector space class class VectorSpaceTy a b | a - > b where dimension :: a -> Integer basis :: (Field c) => a -> [b c] where `b' is a vector space over the field `c'. Suppose I have a haskell function `f :: a c -> b c' representing a linear transformation between (elements) of two vector spaces. I can write transformationMatrix :: VectorSpaceTy ta a -> VectorSpaceTy tb b -> (a c -> b c) -> Matrix c to compute the matrix of the linear transformation. Another alternative is something like ModuleBasis from the numeric prelude: class (Module.C a v) => C a v where {- | basis of the module with respect to the scalar type, the result must be independent of argument, 'Prelude.undefined' should suffice. -} basis :: a -> [v] To compute the basis (for type reasons?) basis needs an (ignored) element of the vector space, but this seems ugly to me. In my case, the vector space is the space of modular forms. Computing a basis requires a tremendous amount of work. I only want to do it once. The ...Ty object gives me a place to stash the result. How would you do this? Cotton On Thu, Jul 3, 2008 at 7:01 AM, DavidA <[EMAIL PROTECTED]> wrote: > Slightly off-topic - but I'm curious to know why you want objects representing > the structures as well as the elements - what will they be used for? > > ___ > Haskell-Cafe mailing list > Haskell-Cafe@haskell.org > http://www.haskell.org/mailman/listinfo/haskell-cafe > ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: type classes
Slightly off-topic - but I'm curious to know why you want objects representing the structures as well as the elements - what will they be used for? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Type classes: Missing language feature?
DavidA wrote: > > newtype Lex = Lex Monomial deriving (Eq) > newtype Glex = Glex Monomial deriving (Eq) > > Now, what I'd like to do is have Lex and Glex, and any further monomial > orderings I define later, automatically derive Show and Num instances from > Monomial (because it seems like boilerplate to have to define Show and Num > instances by hand). Good news: it's already implemented and called newtype deriving :) http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#newtype-deriving In short, you just write newtype Lex = Lex Monomial deriving (Eq, Show, Num) I guess that the Show instance will add the constructor Lex , though. Regards, apfelmus ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Type classes and type equality
> > - If we permit overlapping instances extension, then a few lines of code > > decide equality for all existing and future types: > > > > class TypeEq x y b | x y -> b > > instance TypeEq x x HTrue > > instance TypeCast HFalse b => TypeEq x y b > > This is exactly what I was after, but it doesn't seem to work in Hugs > - even with overlapping instances and unsafe overlapping instances > turned on. Hugs is indeed quite problematic; back in 2004 we essentially gave up on Hugs for anything moderately advanced, especially after Ralf found an example which typechecks only if constraints are specified in a particular order. If we permute the constraints (I think, it was in the instance declaration), Hugs complaints. Clearly the order of constraints should not matter. It has been my experience that the code requiring undecidable instances on GHC might not work on Hugs, failing with sometimes bizarre error messages. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Type classes and type equality
On Wed, Apr 18, 2007 at 01:47:04AM +0100, Neil Mitchell wrote: > >- If we permit undecidable instances, one may assign numerals to > >types. This gives us total order and hence comparison on types. > >In this approach, we only need N instances to cover N types. This is > >still better than Typeable because the equality is decided and can be > >acted upon at compile time. > > In my particular case whether I act at compile time or run time is > unimportant, but obviously this is an important advantage in general. > Unfortunately a cost of one instance per type is still higher than I'd > like to pay :-) Now, it requires one line of code: {-# OPTIONS_DERIVE --derive=TTypeable #-} Stefan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Type classes and type equality
Hi I guess it depends on how many extensions one may wish to enable. At the very least we need multi-parameter type classes with functional dependencies (because that's what TypeEq is in any case). - If we permit no other extension, we need N^2 instances to compare N classes for equality (basically, for each type we should say how it compares to the others). This is not practical except in very limited circumstances. - If we permit undecidable instances, one may assign numerals to types. This gives us total order and hence comparison on types. In this approach, we only need N instances to cover N types. This is still better than Typeable because the equality is decided and can be acted upon at compile time. In my particular case whether I act at compile time or run time is unimportant, but obviously this is an important advantage in general. Unfortunately a cost of one instance per type is still higher than I'd like to pay :-) - If we permit overlapping instances extension, then a few lines of code decide equality for all existing and future types: class TypeEq x y b | x y -> b instance TypeEq x x HTrue instance TypeCast HFalse b => TypeEq x y b This is exactly what I was after, but it doesn't seem to work in Hugs - even with overlapping instances and unsafe overlapping instances turned on. *** This instance: TypeEq a b c *** Conflicts with : TypeEq a a HTrue *** For class: TypeEq a b c *** Under dependency : a b -> c Is there any way to modify this to allow it to work under Hugs as well? Thanks very much for your help, Neil ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Type classes and type equality
> Thanks for pointing that out. As far as I can see, this requires a new > instance declaration for every type? I guess it depends on how many extensions one may wish to enable. At the very least we need multi-parameter type classes with functional dependencies (because that's what TypeEq is in any case). - If we permit no other extension, we need N^2 instances to compare N classes for equality (basically, for each type we should say how it compares to the others). This is not practical except in very limited circumstances. - If we permit undecidable instances, one may assign numerals to types. This gives us total order and hence comparison on types. In this approach, we only need N instances to cover N types. This is still better than Typeable because the equality is decided and can be acted upon at compile time. - If we permit overlapping instances extension, then a few lines of code decide equality for all existing and future types: class TypeEq x y b | x y -> b instance TypeEq x x HTrue instance TypeCast HFalse b => TypeEq x y b Please see http://www.haskell.org/pipermail/haskell-cafe/2006-November/019705.html for some less conventional application, with the complete code. > I was really hoping for something that requires less work on behalf of > the user. The latter approach may be suitable then. It requires no work on behalf of the user at all: the type comparison is universal. http://darcs.haskell.org/HList There is also an issue of ground vs unground types. All the approaches above can decide equality for sufficiently grounded types. That is, two types can be decided equal only if they are ground. The disequality may be decided for partially ground types. If the types are non-ground, the TypeEq constraint flows up, to be resolved when the types are sufficiently instantiated. It is possible to decide equality of non-ground types and even naked type variables. That is a separate discussion. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Type classes and type equality
Hi Oleg, > I'm looking for a type class which checks whether two types are the > same or not. For the full discussion of various solutions, please see Section 9 and Appendix D of the HList paper: http://homepages.cwi.nl/~ralf/HList/paper.pdf Thanks for pointing that out. As far as I can see, this requires a new instance declaration for every type? In this sense, it would require as many Typeable declarations, but have the downside that it isn't build into any compiler. I was really hoping for something that requires less work on behalf of the user. Thanks Neil ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Type classes and type equality
Neil Mitchell wrote: > I'm looking for a type class which checks whether two types are the > same or not. This problem is more complex than appears. It has been solved, however. IncoherentInstances are not required, as IncoherentInstances are generally unsafe. For the full discussion of various solutions, please see Section 9 and Appendix D of the HList paper: http://homepages.cwi.nl/~ralf/HList/paper.pdf The HList code is available http://darcs.haskell.org/HList/ It includes the examples from the paper. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Type classes
> "Stefan" == Stefan Holdermans <[EMAIL PROTECTED]> writes: Stefan> Max, >>> class DatabaseEntry e where entryLabel :: e -> String formatEntry >>> :: e -> String compareEntries :: e -> e -> Ordering >> Then I define >> >>> data Entry = forall a. (DatabaseEntry a) => Entry a >> >>> instance DatabaseEntry Entry where entryLabel (Entry e) = >>> entryLabel e formatEntry (Entry e) = formatEntry e >> How can I define compareEntries for this instance? Stefan> In general: you can't. The field of the Entry constructor has Stefan> a existentially quantified typed. Given two arbitrary values Stefan> of type Entry, this type may be instantiated with a different Stefan> type for each value, so you cannot easily compare the fields. Yes, this require something like multimethods in CLOS. Stefan> If you extend the DatabaseEntry class such that it supplies a Stefan> method that allows to produce some canonical representation Stefan> for database entries suited for comparison, then you could Stefan> take that road. Stefan> Are you sure that your Entry type needs to be existentially Stefan> quantified? I want a map of entries (mapping lables to entries). Generally each style can define its own data types for database objects. Converting entries from data BibEntry = { beLabel :: String , beKind :: String , beProperties :: Map.Map String String } is some sort of "static type checking" of the database. -- WBR, Max Vasin. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Type classes
Then you should produce 'some canonical representation for database entries suited for comparison', like Stefan mentioned. For example: > data Entry = forall a. (DatabaseEntry a) => Entry a > > instance DatabaseEntry Entry where >entryLabel (Entry e) = entryLabel e >formatEntry (Entry e) = formatEntry e >compareEntries (Entry x) (Entry y) = compare (entryLabel x) (entryLabel y) Gerrit Max Vasin wrote: "Geest," == Geest, G van den <[EMAIL PROTECTED]> writes: Geest,> I suppose you want to define compareEntries like this: compareEntries (Entry x) (Entry y) = compareEntries x y Geest,> An option is to just implement it the following way Geest,> (Haskell98!): class DatabaseEntry e where entryLabel :: e -> String formatEntry :: e -> String compareEntries :: e -> e -> Ordering data Entry a = Entry a No. I don't want that. The database parsing function returns Map.Map String Entry but entries can of different types (and these type vary over styles). ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Type classes
> "Geest," == Geest, G van den <[EMAIL PROTECTED]> writes: Geest,> I suppose you want to define compareEntries like this: >> compareEntries (Entry x) (Entry y) = compareEntries x y Geest,> An option is to just implement it the following way Geest,> (Haskell98!): >> class DatabaseEntry e where entryLabel :: e -> String formatEntry >> :: e -> String compareEntries :: e -> e -> Ordering >> >> data Entry a = Entry a No. I don't want that. The database parsing function returns Map.Map String Entry but entries can of different types (and these type vary over styles). -- WBR, Max Vasin. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Type classes and definite types
Hi Bryn Keller, The solution for your problem is very simple. You just have to fetch all values as strings. In this way the library will do all required conversions for you. printRow stmt = do id <- getFieldValue stmt "ID" code <- getFieldValue stmt "Code" name <- getFieldValue stmt "Name" putStrLn (unwords [id, code, name]) Cheers, Krasimir On 5/6/05, Bryn Keller <[EMAIL PROTECTED]> wrote: > Max Vasin wrote: > > >Bryn Keller <[EMAIL PROTECTED]> writes: > > > > > > > >>Hi Max, > >> > >> > >Hello Bryn, > > > > > > > >>Thanks for pointing this out. It's odd that I don't see that anywhere > >>in the docs at the HToolkit site: > >>http://htoolkit.sourceforge.net/doc/hsql/Database.HSQL.html but GHC > >>certainly believes it exists. However, this doesn't actually solve the > >>problem. Substituting toSqlValue for show in printRow' gives the same > >>compile error: > >> > >>Main.hs:22:18: > >>Ambiguous type variable `a' in the constraint: > >> `SqlBind a' arising from use of `getFieldValue' at Main.hs:22:18-30 > >>Probable fix: add a type signature that fixes these type variable(s) > >> > >>So, like with (show (read s)), we still can't use the function until > >>we've established a definite type for the value, not just a type > >>class. > >> > >> > >Yeah... > >Some more RTFSing shows that we have the > > > >getFieldValueType :: Statement -> String -> (SqlType, Bool) > > > >which allows us to write > > > >printRow stmt = do (id :: Int) <- getFieldValue stmt "ID" > > let (codeType, _) = getFieldValueType stmt "Code" > > codestr <- case codeType of > > SqlChar _ -> do (c :: String) <- > > getFieldValue stmt "Code" > > return (toSqlValue c) > > SqlInteger -> do (i :: Int) <- > > getFieldValue stmt "Code" > >return (toSqlValue i) > > -- etc for all SqlType data constructors > > putStrLn (unwords [show id, codestr]) > > > >At least it compiles. But it's ugly :-( > > > > > Ah, good point! Ugly it may be, but at least it works. Thanks for the idea! > > Bryn > ___ > Haskell-Cafe mailing list > Haskell-Cafe@haskell.org > http://www.haskell.org/mailman/listinfo/haskell-cafe > ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Type classes and definite types
Max Vasin wrote: Bryn Keller <[EMAIL PROTECTED]> writes: Hi Max, Hello Bryn, Thanks for pointing this out. It's odd that I don't see that anywhere in the docs at the HToolkit site: http://htoolkit.sourceforge.net/doc/hsql/Database.HSQL.html but GHC certainly believes it exists. However, this doesn't actually solve the problem. Substituting toSqlValue for show in printRow' gives the same compile error: Main.hs:22:18: Ambiguous type variable `a' in the constraint: `SqlBind a' arising from use of `getFieldValue' at Main.hs:22:18-30 Probable fix: add a type signature that fixes these type variable(s) So, like with (show (read s)), we still can't use the function until we've established a definite type for the value, not just a type class. Yeah... Some more RTFSing shows that we have the getFieldValueType :: Statement -> String -> (SqlType, Bool) which allows us to write printRow stmt = do (id :: Int) <- getFieldValue stmt "ID" let (codeType, _) = getFieldValueType stmt "Code" codestr <- case codeType of SqlChar _ -> do (c :: String) <- getFieldValue stmt "Code" return (toSqlValue c) SqlInteger -> do (i :: Int) <- getFieldValue stmt "Code" return (toSqlValue i) -- etc for all SqlType data constructors putStrLn (unwords [show id, codestr]) At least it compiles. But it's ugly :-( Ah, good point! Ugly it may be, but at least it works. Thanks for the idea! Bryn ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Type classes and definite types
Bryn Keller <[EMAIL PROTECTED]> writes: > Hi Max, Hello Bryn, > Thanks for pointing this out. It's odd that I don't see that anywhere > in the docs at the HToolkit site: > http://htoolkit.sourceforge.net/doc/hsql/Database.HSQL.html but GHC > certainly believes it exists. However, this doesn't actually solve the > problem. Substituting toSqlValue for show in printRow' gives the same > compile error: > > Main.hs:22:18: > Ambiguous type variable `a' in the constraint: > `SqlBind a' arising from use of `getFieldValue' at Main.hs:22:18-30 > Probable fix: add a type signature that fixes these type variable(s) > > So, like with (show (read s)), we still can't use the function until > we've established a definite type for the value, not just a type > class. Yeah... Some more RTFSing shows that we have the getFieldValueType :: Statement -> String -> (SqlType, Bool) which allows us to write printRow stmt = do (id :: Int) <- getFieldValue stmt "ID" let (codeType, _) = getFieldValueType stmt "Code" codestr <- case codeType of SqlChar _ -> do (c :: String) <- getFieldValue stmt "Code" return (toSqlValue c) SqlInteger -> do (i :: Int) <- getFieldValue stmt "Code" return (toSqlValue i) -- etc for all SqlType data constructors putStrLn (unwords [show id, codestr]) At least it compiles. But it's ugly :-( -- WBR, Max Vasin. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Type classes and definite types
Max Vasin wrote: Bryn Keller <[EMAIL PROTECTED]> writes: Hi folks, Hello, [skip] The problem is that getFieldValue returns a value of type (SqlBind a) => a. That is, there's no type information associated with this return value other than it's a valid SQL value. There are no operations in the SqlBind class, it's just a marker as near as I can tell. As of HSQL 1.4 this class has method toSqlValue :: a -> String which probably can help you (I really don't know). Some RTFSing shows that in most cases toSqlValue is implemented with show. Hi Max, Thanks for pointing this out. It's odd that I don't see that anywhere in the docs at the HToolkit site: http://htoolkit.sourceforge.net/doc/hsql/Database.HSQL.html but GHC certainly believes it exists. However, this doesn't actually solve the problem. Substituting toSqlValue for show in printRow' gives the same compile error: Main.hs:22:18: Ambiguous type variable `a' in the constraint: `SqlBind a' arising from use of `getFieldValue' at Main.hs:22:18-30 Probable fix: add a type signature that fixes these type variable(s) So, like with (show (read s)), we still can't use the function until we've established a definite type for the value, not just a type class. Bryn ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Type classes and definite types
Bryn Keller <[EMAIL PROTECTED]> writes: > Hi folks, Hello, [skip] > The problem is that getFieldValue returns a value of type (SqlBind a) > => a. That is, there's no type information associated with this return > value other than it's a valid SQL value. There are no operations in > the SqlBind class, it's just a marker as near as I can tell. As of HSQL 1.4 this class has method toSqlValue :: a -> String which probably can help you (I really don't know). Some RTFSing shows that in most cases toSqlValue is implemented with show. -- WBR, Max Vasin. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe