Re: [Haskell-cafe] ghc static linking on Windows
You cannot link statically to a .dll file. Either link statically with the so-called import library (.lib) (there are tools to generate one from a .dll, I believe), or link statically with a static build of SQLite, which is also a .lib file. Hope that helps, Thomas On Wed, Jul 1, 2009 at 19:18, GüŸnther Schmidtgue.schm...@web.de wrote: Hi, I tried to compile an app that uses sqlite3.dll with the -optl-static flag and the error message is: C:\ghc\ghc-6.10.3\gcc-lib\ld.exe: cannot find -lsqlite3 collect2: ld returned 1 exit status ___ 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] golf, predicate check function for MonadPlus (was Re: How to read safely?)
Dan Doel dan.d...@gmail.com writes: There was talk of adding a readMaybe a while ago, but apparently it never happened. As it is, you can use reads, read s becomes: case reads s of [(a, rest)] | all isSpace rest - code using a _ - error case which ensures that you have an unambiguous parse with only trailing whitespace. You can, of course, modify that if you don't care about ambiguity or trailing characters. I was wondering about a more algebraic way of writing that; here's a version (that doesn't care about ambiguity) readMaybe :: Read a = String - Maybe a readMaybe = join . fmap no_trailing_garbage . listToMaybe . reads where no_trailing_garbage = fmap fst . check (all isSpace . snd) check :: (MonadPlus m) = (a - Bool) - a - m a check p a | p a = return a | otherwise = mzero I tried Hoogling for a function like check, but couldn't find it. Surely there's one in a library somewhere? It looks useful to me. (I'm rather taken by way the check (all isSpace . snd) part reads) Monad.guard comes close but fails to get the cigar; in fact guard b == check (const b) () So check is more general. Also, I don't see a singletonListToMaybe that one could use in place of listToMaybe to require unambiguity. Could do isSingleton [a] = True isSingleton _ = False and then use listToMaybe . join . check isSingleton -- aha! Another use for check! Jón [Footnote: I thought of writing guard == flip (check . const) () but then realised it was pointless] -- Jón Fairbairn jon.fairba...@cl.cam.ac.uk ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Monad Input/Output and Monad Transformers
1. Learning haskell I discovered that I/O should be avoided nearly 'at all costs'. The problem is that the IO monad is the only one which have more interactive work flow. There is Reader/Writer monad but in fact AFAIU first one is about the environment and second one is about logging. Implementation of Writer can be defined in terms of handles but it is rather limited (either non-full implementation which may be confusing or need of caching the result for pass etc.). I searched the hackage but I didn't find package with pure I/O. Such package may look like: class (Monad m, Monoid v) = MonadInput v m where -- | Gets an element from input (line of text [with \n], 4096 bytes, -- or something like that). mzero on end getChunk :: m v class (Monad m, Monoid v) = MonadOutput v m where -- | Puts an element putChunk :: v - m () In similar way filters (for example buffered input) can be defined: class (MonadInput v m) = MonadBufferedInput m where -- | If not whole chunk has been consumed at once (for example only -- first 3 elements from list) rest can be returned. It will be -- returned as part of the input on next getChunk call. returnChunk :: v - m () data (MonadInput v m, Monoid v) = BufferedInputT v m a = BufferedInputT a v Also pipes may be defined (as far as I understand but I'm not 100% sure) which probably will simplify the writing of network tests: -- | Evaluates the first argument. If the getChunk is called the -- evaluation is passed to second argument until the putChunk is -- called, which argument is returned in the first argument callPipeT :: (Monad m, Monoid v) = PipeInputT v m a - PipeOutputT v m b - m (a, b) I've started some tests but I'd be grateful for comments (well - probably I'm not the first who come to this idea so a) there is such package or b) my level of Haskell does not allow me to see the problems). 2. I find writing monad transformers annoying. Additionally if package defines transformer A and another transformer B they need to be connected 'by hand'. I find a simple solution which probably is incorrect as it hasn't been used: instance (MonadState s n, Monad (m n), MonadTrans m) = MonadState s (m n) where get = lift get put = lift . put (requires FlexibleInstances MultiParamTypeClasses FlexibleContexts UndecidableInstances - two last are not extensions used by mtl) Regards ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monad Input/Output and Monad Transformers
Hello Maciej, Thursday, July 2, 2009, 3:31:59 PM, you wrote: class (Monad m, Monoid v) = MonadInput v m where -- | Gets an element from input (line of text [with \n], 4096 bytes, -- or something like that). mzero on end getChunk :: m v class (Monad m, Monoid v) = MonadOutput v m where -- | Puts an element putChunk :: v - m () how about interact function? -- Best regards, Bulatmailto:bulat.zigans...@gmail.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monoid wants a (++) equivalent
Ross Paterson wrote: On Wed, Jul 01, 2009 at 10:55:39AM -0700, Bryan O'Sullivan wrote: Okay, here's a tentative plan that will help to figure out the answer. I'll build a fiddled base package that rewires the Monoid class to have (++) be the binary operator, and mappend as a synonym for it. I'll import the Monoid (++) into the Prelude. I'll see how much breaks. If that much builds smoothly, I'll see how much of the rest of Hackage builds, both with and without this custom base package. I'll follow up here with the results, along with a suggestion of how acceptable I think the observed level of breakage is. Generalizing (++) will break some Haskell 98 code, e.g. append = (++) I think that's a show-stopper. I agree it's an issue; and it's the reason I didn't even suggest it myself, favouring a new symbol. I don't think it's a show stopper, in principle. In principle you can imagine a -h98 flag which you pass to compilers which choose a strictly h98-compliant prelude as opposed to a slightly generalised newer one. I'm not the person who would have to maintain that arrangement. I guess that's a call for the people who would have to do the work. There is already a haskell98 package, I think, which is the first step? Jules ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monad Input/Output and Monad Transformers
On Thu, 2009-07-02 at 15:43 +0400, Bulat Ziganshin wrote: Hello Maciej, Thursday, July 2, 2009, 3:31:59 PM, you wrote: class (Monad m, Monoid v) = MonadInput v m where -- | Gets an element from input (line of text [with \n], 4096 bytes, -- or something like that). mzero on end getChunk :: m v class (Monad m, Monoid v) = MonadOutput v m where -- | Puts an element putChunk :: v - m () how about interact function? Well. As far as I know there is no way of using it with network. Additionally there is hard to put monadic code in it: myFunc :: (MonadInput i, MonadOutput o) = (String - m a) - MyMonad i o m [a] If m == IO - which may be a case in normal code it requires unsafePerformIO with all it's problems. In testing I can use pipes and Identity simplifying the whole testing - allowing user to use it's own monads. The other problem is that the order sometimes matters. Consider: main = interact (\x - What's your name?\n ++ Hello:\n ++ x) For human being it is annoying but sometimes it is for example against RFC. Regards ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Fun with type functions
Friends Ken, Oleg, and I have finished Version 2 of our paper Fun with Type Functions, which gives a programmer's tour of what type functions are and how they are useful. http://haskell.org/haskellwiki/Simonpj/Talk:FunWithTypeFuns If you have a moment to look at, and wanted to help us improve it, the above link goes to a wiki page where you can comment on the paper or discuss it. We still have time to improve it. Thanks Simon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Monoid wants a (++) equivalent
Ross Paterson wrote: On Wed, Jul 01, 2009 at 04:53:05PM +0200, Thomas Davie wrote: On 1 Jul 2009, at 16:46, Edward Kmett wrote: I'm rather fond of the () suggestion, but would be happy with anything better than mappend! ;) I find it rather ugly, it has a lot of connotations of does not equals from other languages. Forget Pascal: think of it as a diamond. I too like shiny diamonds, as exemplified in http://apfelmus.nfshost.com/monoid-fingertree.html Regards, apfelmus -- http://apfelmus.nfshost.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] A Strict GCL Interpreter in Haskell
Hi everyone! (First of all, I don't know Monads!) I made a GCL (Guarded Command Language) Compiler and Interpreter for my Languages and Machines course in my University with alex, happy and ghc. I still have a doubt: 1) Since Haskell is Lazy, and my GCL program is being interpreted in Haskell then my GCL is Lazy too (I know is not as simple as that but believe me, somehow it is behaving lazy). The problem is that it can't be lazy (said to me by my teacher on monday) so I tried using seq, but it didn't work, I'll paste the code after this: Programs in GCL like: a) var i : value main i - 1 / 0 end b) var i : value main i - 1 / 0; show i end c) var i : value var foo : array of 2 main i - foo[42] end d) var i : value var foo : array of 2 main i - foo[42]; show i end act like this: a and c finish interpretation b throws division by zero error and finish interpretation d throws index out of bounds error and finish interpretation Now the code: (it is in Spanish. ListLValue is a List of L-Values for the assigments, ListExpr is the list of Expressions to be assigned, Tabla is the Symbol Table (Data.Map), actualizarVar updates a Variable in the Symbol Table with the new value valor, ActualizarArray updates the position indice of an array in the Symbol Table. evalExpr evaluates an arithmetic Expression and returns an Int. Inside evalExpr are the verifications for division by zero of modulo by zero.) evalAsignacion:: ListLvalue - ListExpr - Tabla - Tabla evalAsignacion [] [] tabla = tabla evalAsignacion ((Lid id):valueList) (expr:exprList) tabla = let valor = (evalExpr expr tabla) in valor `seq` evalAsignacion valueList exprList (actualizarVar id valor tabla) evalAsignacion ((LArrayPosition id exprArray):valueList) (expr:exprList) tabla = let valor = (evalExpr expr tabla) indice = (evalExpr exprArray tabla) in valor `seq` indice `seq` evalAsignacion valueList exprList (actualizarArray id indice valor tabla) evalExpr:: Expr - Tabla - Int evalExpr expr tabla = let salida = (snd (evalAritmetico expr tabla)) in salida `seq` if (isLeft salida) then error (getLeft salida) else getRight salida --((Int,Int) is the Line and Colum, that's for error reporting) evalAritmetico :: Expr - Tabla - ((Int,Int),(Either String Int)) --LET ME KNOW IF YOU NEED THIS PART TOO Thanks in advance, Hector Guilarte ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monoid wants a (++) equivalent
On Wed, Jul 1, 2009 at 11:26 AM, Ross Patersonr...@soi.city.ac.uk wrote: On Wed, Jul 01, 2009 at 10:55:39AM -0700, Bryan O'Sullivan wrote: Okay, here's a tentative plan that will help to figure out the answer. I'll build a fiddled base package that rewires the Monoid class to have (++) be the binary operator, and mappend as a synonym for it. I'll import the Monoid (++) into the Prelude. I'll see how much breaks. If that much builds smoothly, I'll see how much of the rest of Hackage builds, both with and without this custom base package. I'll follow up here with the results, along with a suggestion of how acceptable I think the observed level of breakage is. Generalizing (++) will break some Haskell 98 code, e.g. append = (++) I think that's a show-stopper. ___ Could we use some default rules to keep H98 code working? I don't know much about defaulting, but times = (*) works fine and defaults to type Integer. Could we not do the same thing with monoids, having monoids default to type []? Alex ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] [ghc] kind of the function arrow
I was just playing around and noticed that the kind of the function arrow in GHC is (?? - ? - *) when I (naively) expected it to be (* - * - *). After looking at (http://hackage.haskell.org/packages/archive/ghc/6.10.2/doc/html/Type.html#5) I see that the kind of (-) means that the parameter type cannot be an unboxed tuple, whilst the result type can be anything. Why is this? After reading this documentation I would expect the kind (? - ? - *). I'm now wondering if the kind of (-) could cause problems if the following style of declaration is requried: type FunArg a b = (a - b, a) *Main :k FunArg FunArg :: * - * - * By using type variables, whose default kind is *, the function type is fixed to use only boxed types. But if one wanted to allow unboxed type parameters the kind would be wrong, and an explicit kind signature of # or ? can't be given as they are not part of Haskell's source language. I guess my question is why the (?? - ? - *) kind on (-) and what to do if synonyms or data types over (-) are required such as the example just stated. I'm just curious. Thanks, Dominic ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monoid wants a (++) equivalent
On Wed, Jul 1, 2009 at 10:11 PM, David Menendezd...@zednenem.com wrote: In Wed, Jul 1, 2009 at 3:38 PM, Thomas Schillingnomin...@googlemail.com wrote: 2009/7/1 David Leimbach leim...@gmail.com Just because the compiler can figure out what I mean because it has a great type system, I might not be able to figure out what I mean a year from now if I see ++ everywhere. Yep, had the same experience. On the one hand, using monoids lets you delay some design decisions for later and lets you reuse more library code. On the other hand, it sometimes makes it really hard to see what the code is actually doing--especially if you use more than one monoid. For this reason on of the first advanced features I implemented in the (yet unreleased) scion IDE library allows you to look up the instantiated type of an identifier. Unfortunately, jumping to the definition (or documentation) of the monoid instance is a bit more difficult. Haddock should allow documentation on instance declarations... I disagree. The solution is to not create instances when it isn't obvious what the instance does. That's why we have Sum and Prod in Data.Monoid instead of declaring instances directly for Int. With Monoid, I'd go further and say that you should not use mempty and mappend unless you are writing polymorphic code. If you are writing to a specific monoid instance, you should use a specific function. -- Dave Menendez d...@zednenem.com http://www.eyrie.org/~zednenem/ ___ I tend to disagree. I think that Haskell has seen a lot of syntax bloat in the interest of monomorphism. We have List.append, Map.union, Set.union, Sequence., etc., all with different notation, even though these all denote the same operation: taking two of (whatever) and combining them into one. With mappend, you know exactly what the function is supposed to do: combine two things together, and it doesn't matter what datatypes you're using, because that's always what it means. Alex ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monoid wants a (++) equivalent
On Thu, Jul 02, 2009 at 12:46:37PM +0100, Jules Bean wrote: I'm not the person who would have to maintain that arrangement. I guess that's a call for the people who would have to do the work. There is already a haskell98 package, I think, which is the first step? The Prelude is in the base package. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Monoid wants a (++) equivalent
Ketil Malde ketil at malde.org writes: You know, this might be the right time to start expanding our vocabulary beyond seven bits. Since we're likely to keep mappend around as an alias for some time, people would have a grace period to adjust. How about U+2295 (circle with plus inside it)? Or, if we would like to stick to the 8-bit subset to keep those 8859-1 users happy, how about ¤ (funny circle over an x, U+00A4) -k I can work with any symbols as long as they are easily typeable. ++ is 3 easy key press. `mappend` is 9. In both cases I don't need to look on keyboard as I know exactly where they are. However there is no way I can remember where U+00A4 is - probably it is not on all keyboards (reversing and @ gives me a lot of problems in UK keyboards. FR keyboards was nightmare just because a few keys where at different place). In fact I'd need to open keyboard mapping and search for symbol. A lot of trouble just for single symbol. To summarise - It doesn't matter is symbol is or isn't in ASCII or ISO 8859-1 as long as it can be produced easily. Regards ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Monoid wants a (++) equivalent
On Thu, Jul 2, 2009 at 6:45 PM, Maciej Piechotka uzytkown...@gmail.comwrote: I can work with any symbols as long as they are easily typeable. ++ is 3 easy key press. `mappend` is 9. In both cases I don't need to look on keyboard as I know exactly where they are. However there is no way I can remember where U+00A4 is - probably it is not on all keyboards (reversing and @ gives me a lot of problems in UK keyboards. FR keyboards was nightmare just because a few keys where at different place). In fact I'd need to open keyboard mapping and search for symbol. A lot of trouble just for single symbol. To summarise - It doesn't matter is symbol is or isn't in ASCII or ISO 8859-1 as long as it can be produced easily. I would like for my font to have a glyph for it as well so my code doesn't look like tofu. -- Johan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] A Strict GCL Interpreter in Haskell
Am Donnerstag 02 Juli 2009 18:35:17 schrieb Hector Guilarte: Hi everyone! (First of all, I don't know Monads!) I made a GCL (Guarded Command Language) Compiler and Interpreter for my Languages and Machines course in my University with alex, happy and ghc. I still have a doubt: 1) Since Haskell is Lazy, and my GCL program is being interpreted in Haskell then my GCL is Lazy too (I know is not as simple as that but believe me, somehow it is behaving lazy). The problem is that it can't be lazy (said to me by my teacher on monday) so I tried using seq, but it didn't work, I'll paste the code after this: Programs in GCL like: a) var i : value main i - 1 / 0 end b) var i : value main i - 1 / 0; show i end c) var i : value var foo : array of 2 main i - foo[42] end d) var i : value var foo : array of 2 main i - foo[42]; show i end act like this: a and c finish interpretation b throws division by zero error and finish interpretation d throws index out of bounds error and finish interpretation Sorry, I don't quite get that. Do you mean that in your interpreter a) and c) run to completion without raising an error, although they should raise an error and terminate upon that? And b) and d) raise their respective error as they should? Or what is the expected behaviour and what is the actual behaviour? Now the code: (it is in Spanish. ListLValue is a List of L-Values for the assigments, ListExpr is the list of Expressions to be assigned, Tabla is the Symbol Table (Data.Map), actualizarVar updates a Variable in the Symbol Table with the new value valor, ActualizarArray updates the position indice of an array in the Symbol Table. evalExpr evaluates an arithmetic Expression and returns an Int. Inside evalExpr are the verifications for division by zero of modulo by zero.) evalAsignacion:: ListLvalue - ListExpr - Tabla - Tabla evalAsignacion [] [] tabla = tabla evalAsignacion ((Lid id):valueList) (expr:exprList) tabla = let valor = (evalExpr expr tabla) in valor `seq` evalAsignacion valueList exprList (actualizarVar id valor tabla) evalAsignacion ((LArrayPosition id exprArray):valueList) (expr:exprList) tabla = let valor = (evalExpr expr tabla) indice = (evalExpr exprArray tabla) in valor `seq` indice `seq` evalAsignacion valueList exprList (actualizarArray id indice valor tabla) evalExpr:: Expr - Tabla - Int evalExpr expr tabla = let salida = (snd (evalAritmetico expr tabla)) in salida `seq` if (isLeft salida) then error (getLeft salida) else getRight salida --((Int,Int) is the Line and Colum, that's for error reporting) evalAritmetico :: Expr - Tabla - ((Int,Int),(Either String Int)) --LET ME KNOW IF YOU NEED THIS PART TOO Thanks in advance, Hector Guilarte ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monoid wants a (++) equivalent
Wed, Jul 1, 2009 at 4:17 PM, Raynor Vliegendhart shinnon...@gmail.comwrote: We could use (Control.Category..) as an operator, but this would require an additional wrapping layer if we wish to use the existing Monoid instances: import Prelude hiding (id, (.)) import Control.Category import Data.Monoid -- Category wrapper for existing Monoid instances newtype MonoidC m a b = MonoidC {unwrapMC :: m} deriving (Show) instance Monoid m = Category (MonoidC m) where id = MonoidC mempty MonoidC m . MonoidC n = MonoidC $ m `mappend` n Furthermore, writing Category instances for monoids require dummy type parameters: -- Example instance newtype SumC m a b = SumC {getSumC :: m} deriving (Show, Eq) instance Num a = Category (SumC a) where id = SumC (fromIntegral 0) SumC x . SumC y = SumC $ x + y I have a monoid-as-category and category-endomorphism as monoid in: http://comonad.com/haskell/monoids/dist/doc/html/monoids/Data-Monoid-Categorical.html but there are issues. 1.) these completely change the typing involved 2.) the monoid as category-with-one-object is pretty scary to someone without a category theory background. 3.) This doesn't properly represent the category-with-one-object because at best the two phantom types yield you something like a category like Hask, which has been fully connected * M where M is the category of your monoid. Even if you use GADTs to cut down the phantom types to one where the head and tail of the arrow are the same object and |.| takes a category to its discrete category (discarding all non-identity arrows) you are looking at a category like |Hask| * M because of the phantom type. data CMonoid m n o where M :: Monoid m = m - CMonoid m a a instance Monoid m = Category (CMonoid m) where id = M mempty M a . M b = M (a `mappend` b) Attempting to go any further and railroad that type to equal m fails when you go to define id. So the categorical notion of a monoid is pretty much a non-starter in Haskell. -Edward Kmett On Another disadvantage of this approach is that we cannot have a default monoid instance for lists (kind mismatch). ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] golf, predicate check function for MonadPlus (was Re: How to read safely?)
On Thu, Jul 2, 2009 at 3:36 AM, Jon Fairbairnjon.fairba...@cl.cam.ac.uk wrote: Dan Doel dan.d...@gmail.com writes: There was talk of adding a readMaybe a while ago, but apparently it never happened. As it is, you can use reads, read s becomes: case reads s of [(a, rest)] | all isSpace rest - code using a _ - error case which ensures that you have an unambiguous parse with only trailing whitespace. You can, of course, modify that if you don't care about ambiguity or trailing characters. I was wondering about a more algebraic way of writing that; here's a version (that doesn't care about ambiguity) readMaybe :: Read a = String - Maybe a readMaybe = join . fmap no_trailing_garbage . listToMaybe . reads where no_trailing_garbage = fmap fst . check (all isSpace . snd) check :: (MonadPlus m) = (a - Bool) - a - m a check p a | p a = return a | otherwise = mzero I tried Hoogling for a function like check, but couldn't find it. Surely there's one in a library somewhere? It looks useful to me. (I'm rather taken by way the check (all isSpace . snd) part reads) Monad.guard comes close but fails to get the cigar; in fact guard b == check (const b) () So check is more general. Also, I don't see a singletonListToMaybe that one could use in place of listToMaybe to require unambiguity. Could do isSingleton [a] = True isSingleton _ = False and then use listToMaybe . join . check isSingleton -- aha! Another use for check! Jón [Footnote: I thought of writing guard == flip (check . const) () but then realised it was pointless] -- Jón Fairbairn jon.fairba...@cl.cam.ac.uk You can use the Kleisli composition operator (=) to make it a little nicer. singletonListToMaybe :: [a] - Maybe a singletonListToMaybe [x] = Just x singletonListToMaybe _ = Nothing check :: MonadPlus m = (a - Bool) - a - m a check p a | p a = return a | otherwise = mzero readMaybe = fmap fst.check (all isSpace.snd) = singletonListToMaybe.reads Alex ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monad Input/Output and Monad Transformers
On Thu, Jul 2, 2009 at 5:31 AM, Maciej Piechotka uzytkown...@gmail.comwrote: 2. I find writing monad transformers annoying. Additionally if package defines transformer A and another transformer B they need to be connected 'by hand'. You have not given any concrete problems or examples, so it's hard for me to comment. But at first glance, I would conjecture that you are relying too heavily on monads and sequential thinking. Consider what your code would look like without a single monad. Obviously you cannot talk to the network without IO, but your program can still be * modeled* purely, and then toss in IO at the last second to tie it to the network. This model may be difficult for you because it requires your brain to be rewired; feel free to mail this list with concrete modeling problems and we will help you out. As for the pure model, throw away Reader, Writer, State -- everything, and just use pure functions. Then add monads back in *at small scopes* when they clean things up. I used to approach problems by designing a monad for my whole program, using an appropriate stack of transformers. I suspect such an approach led to the claim that monads are not appropriate for large software systems in a popular paper a few months ago. As I have gained more experience, I found that this is the *wrong* way to go about using them. Now my primary use of monads is within the scope of a single function, to tie together the helper functions in the where clause. Luke I find a simple solution which probably is incorrect as it hasn't been used: instance (MonadState s n, Monad (m n), MonadTrans m) = MonadState s (m n) where get = lift get put = lift . put (requires FlexibleInstances MultiParamTypeClasses FlexibleContexts UndecidableInstances - two last are not extensions used by mtl) Regards ___ 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] Monad Input/Output and Monad Transformers
On Thu, Jul 2, 2009 at 1:18 PM, Luke Palmer lrpal...@gmail.com wrote: I used to approach problems by designing a monad for my whole program, using an appropriate stack of transformers. I suspect such an approach led to the claim that monads are not appropriate for large software systems in a popular paper a few months ago. Link please! I googled but I couldn't find it :( I'd like to find out what you and the authors have learned about the inappropriateness of monads for large software systems. Thanks, Jason ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re[2]: [Haskell-cafe] Monad Input/Output and Monad Transformers
Hello Luke, Friday, July 3, 2009, 12:18:21 AM, you wrote: I used to approach problems by designing a monad for my whole program, using an appropriate stack of transformers. I suspect such an approach led to the claim that monads are not appropriate for large software systems in a popular paper a few months ago. As I have gained more experience, I found that this is the wrong way to go about using them. was it ghc authors paper? :) -- Best regards, Bulatmailto:bulat.zigans...@gmail.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] ORM for haskell?
Hi Marc Weber Hi Mads! On Tue, Jun 30, 2009 at 11:49:40PM +0200, Mads Lindstrøm wrote: Hi Marc Weber Another example: Updating the age of a pupil: row = SELECT * FROM pupils where age = 13; UPDATE pupils SET age = 14 WHERE id = the id you got above p = session.query(Pupil).filter(Pupil.age==13).one().age=14 session.commit() difference? You don't have to care about ids. you just assign a new value and tell the engine that it should commit. So again less chances to get something wrong. Could you not do in SQL: UPDATE pupils SET age = 14 WHERE age = 13 Of course. But: you can pass around that pupil object to another function and still assign a new age then run session.commit(). When passing around the pupile you can follow the relation_ships (relations?) back to school. def doSomething(pupil): pupil['age'] = 13 pupil.teacher.school.rating += 1 doSomething(session.query(Pupil).filter(Pupil.age==13)) session.commit() Now how would you do this using SQL? As far as I know, you cannot. And it is very nice. On the other hand you sometimes want to execute more of the logic on the DBMS, as it leads to better performance. But maybe we can somehow have our cake and eat it too. E.g. if the user still have some control about where the logic is executed. Sorry about the confustion (relation / relation-ship). I mixed up the terminology. Anyway I guess you can see here how powerful an ORM can be and why we should write such a library for haskell. Don't be sorry about that. I know people often confuse the terms and I could have replied just asking if you had not swapped the two terms. In my native language relation can mean both relation and to relationship. Guess, it is the same in other languages... I think it's very hard to invent such a short synax in haskell cause you have to take monads into account etc.. And it matters how much time you have to spend writing code. Yes and yes. I think (my gut tells me so) you will need to use Template Haskell, if you want something as succinct as the Python code you showed. Or maybe if you give up type safety, but I guess your are not willing to do that. But it could be fun (and challenging) coming up with something really nice. Thanks for your feedback. I hope there will be some more. Marc Weber I may have sounded a bit negative in my previous mails. But I really can see something cool about what you describe. That said, I think people are sometimes too eager to replace SQL. As you properly are already aware, SQL+Relational databases has some very nice properties (list below is form the top of my head, there are other advantages): * They are accessed with a declarative language (SQL) * They can make high-level optimization automatically and guided by the user * They can, transparently, execute queries/updates using multiple servers/CPUs. It may require some changes to the database, but it can be done without changing your SQL * They are based on a nice theoretical foundation * If databases are normalized properly, data are a lot more transparent than other ways of organizing data. At least other ways I have seen. * Normalization provides a lot less ambiguous guidance, than other development methodologies. * Transaction support But as you point out yourself, everything is not rosy. And in addition to what you write, all the (un)marshaling you need when accessing databases from Haskell is quite cumbersome. And I realize that you are not trying to replace RDBs, just building a nicer interface to them. I am just concerned that some of the nice properties are lost in the process. I think my main concern comes from seeing people create databases, by automatically generating tables from OO-classes. They invariably ends up with something not nearly as nice, as if they had constructed the database in a more traditional fashion. To summarize, what you propose is cool. Just do not throw the baby out with the bathwater. Greetings, Mads Lindstrøm signature.asc Description: This is a digitally signed message part ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monad Input/Output and Monad Transformers
On Thu, 2009-07-02 at 14:18 -0600, Luke Palmer wrote: On Thu, Jul 2, 2009 at 5:31 AM, Maciej Piechotka uzytkown...@gmail.com wrote: 2. I find writing monad transformers annoying. Additionally if package defines transformer A and another transformer B they need to be connected 'by hand'. You have not given any concrete problems or examples, so it's hard for me to comment. But at first glance, I would conjecture that you are relying too heavily on monads and sequential thinking. Consider what your code would look like without a single monad. Obviously you cannot talk to the network without IO, but your program can still be modeled purely, and then toss in IO at the last second to tie it to the network. This model may be difficult for you because it requires your brain to be rewired; feel free to mail this list with concrete modeling problems and we will help you out. As for the pure model, throw away Reader, Writer, State -- everything, and just use pure functions. Then add monads back in at small scopes when they clean things up. AFAIU you comment the 2de point only. I look at this moment from library, not program point of view. So consider the library IOMonad which defined some MonadInput v m monad. Then you have NNTP library which has NntpT m monad. Each of them defines appropriate stack such as that NntpT (State s) is instance of MonadState. But if there is NntpT MyInput, where MyInput isinstance of MonadInput, is not MonadInput. To do it with current approach the libraries would have to be interlinked. Also it is quite boring to include for all monad instance ... = ... where f1 = lift f1 f2 = lift f2 ... I used to approach problems by designing a monad for my whole program, using an appropriate stack of transformers. I thought about others which might have want to use my monads in their functions... I suspect such an approach led to the claim that monads are not appropriate for large software systems in a popular paper a few months ago. I'd appreciate the link - google find nothing. I fall in love in Haskell about a week or two ago and I fall in love just after I started learning it ;) As I have gained more experience, I found that this is the wrong way to go about using them. Now my primary use of monads is within the scope of a single function, to tie together the helper functions in the where clause. Luke Regards ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monad Input/Output and Monad Transformers
-BEGIN PGP SIGNED MESSAGE- Hash: SHA512 On Thu, Jul 2, 2009 at 5:05 PM, Maciej Piechotka wrote: I'd appreciate the link - google find nothing. I fall in love in Haskell about a week or two ago and I fall in love just after I started learning it ;) Research programming languages like Haskell [22] and ML [20] didn't seem to offer any near-term solution. Diatchki's work on fine-grain representation in Haskell [25] is not yet main-stream, and had not yet started when we began work on BitC. Support for state in Haskell exists in the form of the I/O monad [23], but in our opinion the monadic idiom does not scale well to large, complexly stateful programs,1 and imposes constraints that are unnatural in the eyes of systems programmers. Oh, and not only do our monads not scale, they're slow to boot: Ultimately, the problem with Haskell and ML for our purposes is that the brightest and most aggressive programmers in those languages, using the most aggressive optimization techniques known to the research community, remain unable to write systems codes that compete reasonably with C or C++. The most successful attempt to date is probably the FoxNet TCP/IP protocol stack, which incurred a 10x increase in system load and a 40x penalty in accessing external memory relative to a conventional (and less aggressively optimized) C implemenation. [ 4 ,6 ] http://www.bitc-lang.org/docs/bitc/bitc-origins.html - -- gwern -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.9 (GNU/Linux) iEYEAREKAAYFAkpNJWoACgkQvpDo5Pfl1oLpeQCcDXUnfBaitwii3rhortVqO8Fr SXIAnAiKY5EGg/ssZHOaooP1ag1xGIE4 =iugB -END PGP SIGNATURE- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] A Strict GCL Interpreter in Haskell
Hi Hector, Hector Guilarte wrote: 1) Since Haskell is Lazy, and my GCL program is being interpreted in Haskell then my GCL is Lazy too (I know is not as simple as that but believe me, somehow it is behaving lazy). The problem is that it can't be lazy (said to me by my teacher on monday). evalExpr:: Expr - Tabla - Int evalExpr expr tabla = let salida = (snd (evalAritmetico expr tabla)) in salida `seq` if (isLeft salida) then error (getLeft salida) else getRight salida I think the problem with your code is that you call error, instead of reporting the error back to the caller. evalExpr can go wrong (consider 5 / 0), but this fact is not represented in the type: evalExpr:: Expr - Tabla - Int The type says that for all expressions and all symbol tables, you can produce an int result. But that is not true! So try using this more adequate type: evalExpr :: Expr - Tabla - Either String Int Now, for all expressions and symbol tables, evalExpr either can compute an integer result, or it informs you that something went wrong. If you have these kinds of types on all your functions, your main program becomes something like: main = do code - readAndParseFile somefile case evalProgram code of Left error - putStrLn (Error: ++ error) Right () - putStrLn Worked fine! So if you need fine-grained control over error-handling, add explicit error handling, and do not use the error function. Good luck! Tillmann ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Flipping *-*-* kinds, or monadic finally-tagless madness
I'm trying to write HOAS Show instances for the finally-tagless type-classes using actual State monads. The original code: http://okmij.org/ftp/Computation/FLOLAC/EvalTaglessF.hs Two type variables are needed: one to vary over the Symantics class (but only as a phantom type) and another to vary over the Monad class. Hence, the use of 2-variable type constructors. type VarCount = int newtype Y b a = Y {unY :: VarCount - (b, VarCount)} Not knowing of a type-level 'flip', I resort to newtype isomorphisms: newtype Z a b = Z {unZ :: Y b a} instance Monad (Z a) where return x = Z $ Y $ \c - (x,c) (Z (Y m)) = f = Z $ Y $ \c0 - let (x,c1) = m c0 in (unY . unZ) (f x) c1-- Pace, too-strict puritans instance MonadState String (Z a) where get = Z $ Y $ \c - (show c, c) put x = Z $ Y $ \_ - ((), read x) So far so good. Now for the Symantics instances (abridged). class Symantics repr where int :: Int - repr Int -- int literal add :: repr Int - repr Int - repr Int lam :: (repr a - repr b) - repr (a-b) instance Symantics (Y String) where int = unZ . return . show add x y = unZ $ do sx - Z x sy - Z y return $ ( ++ sx ++ + ++ sy ++ ) The add function illustrates the kind of do-sugaring we know and love that I want to use for Symantics. lam f = unZ $ do show_c0 - get let vname = v ++ show_c0 c0 = read show_c0 :: VarCount c1 = succ c0 fz :: Z a String - Z b String fz = Z . f . unZ put (show c1) s - (fz . return) vname return $ (\\ ++ vname ++ - ++ s ++ ) Now with lam, I get this cryptic error message (under 6.8.2): Occurs check: cannot construct the infinite type: b = a - b When trying to generalise the type inferred for `lam' Signature type: forall a1 b1. (Y String a1 - Y String b1) - Y String (a1 - b1) Type to generalise: forall a1 b1. (Y String a1 - Y String b1) - Y String (a1 - b1) In the instance declaration for `Symantics (Y String)' Both the two types in the error message are identical, which suggests no generalization is needed. I'm puzzled why ghc sees an infinite type. Any ideas on how to proceed? -- View this message in context: http://www.nabble.com/Flipping-*-%3E*-%3E*-kinds%2C-or-monadic-finally-tagless-madness-tp24314553p24314553.html Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Network.CGI -- practical web programming example.
Brandon S. Allbery KF8NH wrote: Some Haskell programmers use fmap (because most Monads are also Functors), others use liftM. Both have the same effect: given a monadic computation m a, liftM f turns f into a function that operates on the enclosed a instead of the entire m a. That is, given the theory behind it all, every monad is a functor (note the lower case); from which it follows that liftM == fmap. For historical reasons the Monad typeclass does not require a Functor instance, however, and so it's not the case that every Monad is also a Functor (note the upper case). The function liftM can be defined generically given definitions for return and (=), so some prefer to use liftM to avoid the extra Functor dependency. The function fmap can be given specialized definitions due to overloading, so others prefer to use it for efficiency reasons. The ($) function is just a symbolic name for fmap. You'll also see the Applicative typeclass for applicative functors. Applicative does require a Functor instance, which is good. (And actually, every monad is an applicative functor; though the Monad class doesn't require Applicative either.) The function liftA can be defined generically given definitions for pure and (*), and liftA == fmap as well. The only reason anyone should use liftA is for defining a Functor instance when they're too lazy to give a specialized implementation. -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] ORM for haskell?
And I realize that you are not trying to replace RDBs, just building a nicer interface to them. I am just concerned that some of the nice properties are lost in the process. I think my main concern comes from seeing people create databases, by automatically generating tables from OO-classes. They invariably ends up with something not nearly as nice, as if they had constructed the database in a more traditional fashion. To summarize, what you propose is cool. Just do not throw the baby out with the bathwater. Hi Mad. Maybe I want to replace a RDBMS. But this will cost. You can fire arbitrary SQL statements in no time at RDBMS. You can't do things like that that easy using a haskell (in memory) only solutions. So SQL wins here at the moment if you want to be productive. If you read the .pdf I posted you saw that SQLAlchemy is that coold that a) you can use the shortcut style and define objects and tables at the same time but you als can b) define both layers independent of each other. And: Most applications today don't have to scale to an extend forcing you to move all logic into a database system. If you can one request a sec on a web application .. That's already very much for most small shop system. (I'm not talking about Amazon or ebay or such!) I'm talking about customers who want some more customizations as you can do with oscommerce. My main purpose was to see wether someone else would be interested in spending more effort into such a solution. Anyway I have still have to do some other work before I can jump into such a project. And Mad, I think you already know that RDBMS are not the best solution because it's very hard to ask a RDBMS wether a query retuns a nullable value or not. And that makes a huge difference wether you have to use a unsafeFromNull like function all the time or not. Time will tell how much energy I can spend on such this topic in the future. cu all Marc Weber ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monoid wants a (++) equivalent
It is claimed that making ++ become another name for the Monoid mappend operation will break some Haskell 98 code such as append = (++) That example can easily be fixed by adding a type signature, no? append :: [a] - [a] - [a] append = (++) In ghci, at any rate, using mappend instead of (++), the first is rejected, but the sceond works perfectly. The nice thing about this is that the code _with_ the type signature is perfectly legal Haskell 98, so the fix leaves you with something that works with either reading of (++). Do we have any other uses of ++ that would be hard to fix by adding a type signature? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] A Strict GCL Interpreter in Haskell
Hi Hector, Hector Guilarte wrote: I did that already, but it didn't work... Also, since this kind of error would be a run time error in my GCL Language, I don't want it to continue executing whenever an error is found, that's why I changed it back to just: evalExpr:: Expr - Tabla - Int Instead of using the Either String Int... I think you misunderstand something. If you use (Expr - Table - Int), you are announcing: Whatever happens, I keep executing. If you use (Expr - Table - Either String Int), you are announcing: I may stop earlier because of some problem. Since may you want to stop earlier, you should use the second type. Let's look at a very small example, an interpreter for the following little language: data Expression = Literal Integer | Add Expression Expression | Divide Expression Expression Because of division by zero, an interpreter for this language may fail. So we have two kinds of return values: Sometimes we return a number, and sometimes we return an DivideByZero error. We can reflect that in a datatype: data Result = Number Integer | DivideByZeroError Now we can write our interpreter: eval :: Expression - Result eval (Literal n) = Number n eval (Add a b) = case eval a of Number result_of_a - case b of Number result_of_b - Number (result_of_a + result_of_b) DivideByZeroError - DivideByZeroError DivideByZeroError - DivideByZeroError eval (Add a b) = case eval a of Number result_of_a - case b of Number result_of_b - if b == 0 then DivideByZeroError else Number (result_of_a + result_of_b) DivideByZeroError - DivideByZeroError DivideByZeroError - DivideByZeroError This interpreter will stop as soon as it encounters a division by zero, because we take care to return DivideByZeroError whenever we see a DivideByZeroError in one of the subterms. So you have to use an appropriate return type (like (Either String Int) or Result), and you have to pattern match on the result of earlier parts of your program, and propagate the error. Tillmann ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Network.CGI -- practical web programming example.
On Jul 2, 2009, at 17:59 , wren ng thornton wrote: Brandon S. Allbery KF8NH wrote: Some Haskell programmers use fmap (because most Monads are also Functors), others use liftM. Both have the same effect: given a monadic computation m a, liftM f turns f into a function that operates on the enclosed a instead of the entire m a. That is, given the theory behind it all, every monad is a functor (note the lower case); from Yeh, I decided to bypass the whole all monads are functors, but for Hysterical Raisins not all Monads are Functors morass. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allb...@kf8nh.com system administrator [openafs,heimdal,too many hats] allb...@ece.cmu.edu electrical and computer engineering, carnegie mellon universityKF8NH PGP.sig Description: This is a digitally signed message part ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Flipping *-*-* kinds, or monadic finally-tagless madness
Kim-Ee Yeoh wrote: The add function illustrates the kind of do-sugaring we know and love that I want to use for Symantics. lam f = unZ $ do show_c0 - get let vname = v ++ show_c0 c0 = read show_c0 :: VarCount c1 = succ c0 fz :: Z a String - Z b String fz = Z . f . unZ put (show c1) s - (fz . return) vname return $ (\\ ++ vname ++ - ++ s ++ ) Now with lam, I get this cryptic error message (under 6.8.2): Occurs check: cannot construct the infinite type: b = a - b When trying to generalise the type inferred for `lam' Signature type: forall a1 b1. (Y String a1 - Y String b1) - Y String (a1 - b1) Type to generalise: forall a1 b1. (Y String a1 - Y String b1) - Y String (a1 - b1) In the instance declaration for `Symantics (Y String)' Both the two types in the error message are identical, which suggests no generalization is needed. I'm puzzled why ghc sees an infinite type. Any ideas on how to proceed? Not an answer, but just a different error message from GHC 6.10.3 when I tried loading up your code. kya...@kyavaio:~/tmp$ ghci EvalTaglessF.hs GHCi, version 6.10.3: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer ... linking ... done. Loading package base ... linking ... done. [1 of 1] Compiling Main ( EvalTaglessF.hs, interpreted ) EvalTaglessF.hs:264:14: Couldn't match expected type `b1' against inferred type `b' `b1' is a rigid type variable bound by the type signature for `fz' at EvalTaglessF.hs:263:31 `b' is a rigid type variable bound by the type signature for `lam' at EvalTaglessF.hs:248:26 Expected type: Z b1 String Inferred type: Z b String In the expression: Z . f . unZ In the definition of `fz': fz = Z . f . unZ EvalTaglessF.hs:264:22: Couldn't match expected type `a1' against inferred type `a' `a1' is a rigid type variable bound by the type signature for `fz' at EvalTaglessF.hs:263:17 `a' is a rigid type variable bound by the type signature for `lam' at EvalTaglessF.hs:248:16 Expected type: Z a1 String Inferred type: Z a String In the second argument of `(.)', namely `unZ' In the second argument of `(.)', namely `f . unZ' Failed, modules loaded: none. I hope this gives you a hint, if any. I am not exactly sure about how to solve this but I might try using scoped type variables extension somehow if I were in your shoe. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Flipping *-*-* kinds, or monadic finally-tagless madness
Actually the problem lies in your definition of fz, it has the wrong type to be used in lam. The Z you get out of fz as type Z b String, but you need it to have Z (a - b) String so that when you strip off the Z you have a Y String (a - b) matching the result type of lam. To get there replace your definition of fz with: fz :: Z a String - Z (a - b) String fz = Z . Y . unY . f . unZ In 6.10.2 I used {-# LANGUAGE FlexibleInstances, TypeSynonymInstances, MultiParamTypeClasses, ScopedTypeVariables #-} and that compiled just fine. On Thu, Jul 2, 2009 at 8:02 PM, Ahn, Ki Yung kya...@gmail.com wrote: Kim-Ee Yeoh wrote: The add function illustrates the kind of do-sugaring we know and love that I want to use for Symantics. lam f = unZ $ do show_c0 - get let vname = v ++ show_c0 c0 = read show_c0 :: VarCount c1 = succ c0 fz :: Z a String - Z b String fz = Z . f . unZ put (show c1) s - (fz . return) vname return $ (\\ ++ vname ++ - ++ s ++ ) Now with lam, I get this cryptic error message (under 6.8.2): Occurs check: cannot construct the infinite type: b = a - b When trying to generalise the type inferred for `lam' Signature type: forall a1 b1. (Y String a1 - Y String b1) - Y String (a1 - b1) Type to generalise: forall a1 b1. (Y String a1 - Y String b1) - Y String (a1 - b1) In the instance declaration for `Symantics (Y String)' Both the two types in the error message are identical, which suggests no generalization is needed. I'm puzzled why ghc sees an infinite type. Any ideas on how to proceed? Not an answer, but just a different error message from GHC 6.10.3 when I tried loading up your code. kya...@kyavaio:~/tmp$ ghci EvalTaglessF.hs GHCi, version 6.10.3: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer ... linking ... done. Loading package base ... linking ... done. [1 of 1] Compiling Main ( EvalTaglessF.hs, interpreted ) EvalTaglessF.hs:264:14: Couldn't match expected type `b1' against inferred type `b' `b1' is a rigid type variable bound by the type signature for `fz' at EvalTaglessF.hs:263:31 `b' is a rigid type variable bound by the type signature for `lam' at EvalTaglessF.hs:248:26 Expected type: Z b1 String Inferred type: Z b String In the expression: Z . f . unZ In the definition of `fz': fz = Z . f . unZ EvalTaglessF.hs:264:22: Couldn't match expected type `a1' against inferred type `a' `a1' is a rigid type variable bound by the type signature for `fz' at EvalTaglessF.hs:263:17 `a' is a rigid type variable bound by the type signature for `lam' at EvalTaglessF.hs:248:16 Expected type: Z a1 String Inferred type: Z a String In the second argument of `(.)', namely `unZ' In the second argument of `(.)', namely `f . unZ' Failed, modules loaded: none. I hope this gives you a hint, if any. I am not exactly sure about how to solve this but I might try using scoped type variables extension somehow if I were in your shoe. ___ 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] here is how I made it type check
I don't know if this is what you want but I was at least able to make it to type check basically changing (fz . return) into simply return. I think the error message about the occurs check was because of the fz function is used wrong (or you didn't give it a correct type). {-# LANGUAGE NoMonomorphismRestriction,TypeSynonymInstances,FlexibleInstances,MultiParamTypeClasses,ScopedTypeVariables #-} -- Haskell' Committee seems to have agreed to remove the restriction -- Tagless Typed lambda-calculus with integers and the conditional -- in the higher-order abstract syntax. -- Haskell itself ensures the object terms are well-typed. -- Here we use the tagless final approach. {- module EvalTaglessF where class Symantics repr where l:: (repr t1 - repr t2) - repr (t1-t2) a:: repr (t1-t2) - repr t1 - repr t2 i:: Int - repr Int (+:) :: repr Int - repr Int - repr Int -- addition ifz :: repr Int - repr t - repr t - repr t -- if zero fix :: repr ((a-b) - (a-b)) - repr (a-b) -- Let :: repr t1 - (repr t1 - repr t) - repr t -- compared to EvalTaglessI, everything is in lower-case now -- Since we rely on the metalanguage for typechecking and hence -- type generalization, we have to use `let' of the metalanguage. infixl 9 `a` -- It is quite challenging to show terms. Yet, in contrast to the GADT-based -- approach (EvalTaglessI.hs), we are able to do that, without -- extending our language with auxiliary syntactic forms. -- Incidentally, showing of terms is just another way of _evaluating_ -- them, to strings. type VarCount = Int -- to build the names of variables newtype S t = S (VarCount - (String,VarCount)) evals (S t) = t instance Symantics S where l f = S $ \c0 - let vname = v ++ show c0 c1 = succ c0 (s,c2) = evals (f (S $ \c - (vname,c))) c1 in ((\\ ++ vname ++ - ++ s ++ ),c2) a e1 e2 = S $ \c0 - let (s1,c1) = evals e1 c0 (s2,c2) = evals e2 c1 in (( ++ s1 ++ ++ s2 ++ ),c2) i n = S $ \c - (show n,c) e1 +:e2 = S $ \c0 - let (s1,c1) = evals e1 c0 (s2,c2) = evals e2 c1 in (( ++ s1 ++ + ++ s2 ++ ),c2) ifz e1 e2 e3 = S $ \c0 - let (s1,c1) = evals e1 c0 (s2,c2) = evals e2 c1 (s3,c3) = evals e3 c2 in ((ifz ++ s1 ++ ++ s2 ++ ++ s3 ++),c3) fix e = S $ \c0 - let (s1,c1) = evals e c0 in ((fix ++ s1 ++ ),c1) tshow t = fst $ evals t 0 -- We no longer need variables or the environment and we do -- normalization by evaluation. -- Denotational semantics. Why? newtype D t = D t -- This is not a tag. Why? evald:: D t - t evald (D t) = t instance Symantics D where l f = D $ \x - evald (f (D x)) a e1 e2 = D $ (evald e1) (evald e2) i n = D $ n e1 +: e2 = D $ evald e1 + evald e2 ifz e1 e2 e3 = D $ if evald e1 == 0 then evald e2 else evald e3 fix e= D $ hfix (evald e) where hfix f = f (hfix f) {- We can also give operational semantics, by implementing the function of the following signature: evalo :: (forall repr. Symantics repr = repr t) - (forall repr. Symantics repr = repr t) The signature has rank-2 type and hence this file requires a PRAGMA declaration {-# LANGUAGE Rank2Types #-} The implementation of evalo is exactly the partial evaluator of the tagless final paper. Please see the paper for details. -} -- Tests -- Truly the tests differ from those in EvalTaglessI.hs only in the case -- of `syntax`: (i 1) vs (I 1), etc. test0d = evald $ l(\vx - vx +: (i 2)) `a` (i 1) -- 3 term1 = l (\vx - ifz vx (i 1) (vx +: (i 2))) test11d = evald $ term1 test11s = tshow $ term1 -- (\\v0- (ifz v0 1 (v0 + 2))) test12d = evald (term1 `a` (i 2)) -- 4, as Haskell Int -- test14 = evald (term1 `a` vx) -- Type error! Not in scope: `vx' term2 = l (\vx - l (\vy - vx +: vy)) -- *EvalTaglessF :t term2 -- term2 :: (Symantics repr) = repr (Int - Int - Int) test21 = evald term2 test23d = evald (term2 `a` (i 1) `a` (i 2)) -- 3 termid = l(\vx - vx) testid = evald termid -- testid :: t1 - t1 term2a = l (\vx - l(\vy - vx `a` vy)) {- The meta-language figured the (polymorphic) type now *EvalTaglessF :t term2a term2a :: (Symantics repr) = repr ((t1 - t2) - t1 - t2) -} -- No longer hidden problems -- term3 = l (\vx - ifz vx (i 1) vy) -- Not in scope: `vy' -- The following is a type error, we can't even enter the term -- term4 = l (\vx - ifz vx (i 1) (vx `a` (i 1))) {- Now we get good error messages! Couldn't match expected type `t1 - Int' against inferred type `Int' Expected type: repr (t1 - Int) Inferred type: repr Int In the first argument of `a', namely `vx' In the third argument of `ifz', namely `(vx `a` (i 1))' -} -- (x+1)*y = x*y + y -- why is this less of a cheating? Try showing the term -- Now,
[Haskell-cafe] Re: Flipping *-*-* kinds, or monadic finally-tagless madness
Edward Kmett 쓴 글: Actually the problem lies in your definition of fz, it has the wrong type to be used in lam. The Z you get out of fz as type Z b String, but you need it to have Z (a - b) String so that when you strip off the Z you have a Y String (a - b) matching the result type of lam. To get there replace your definition of fz with: fz :: Z a String - Z (a - b) String fz = Z . Y . unY . f . unZ I think this seems to be the Yeoh wanted. Mine was just blinded hack just to make it type check without looking at what program means. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] [ghc] kind of the function arrow
Dominic Orchard wrote: I was just playing around and noticed that the kind of the function arrow in GHC is (?? - ? - *) when I (naively) expected it to be (* - * - *). After looking at (http://hackage.haskell.org/packages/archive/ghc/6.10.2/doc/html/Type.html#5) I see that the kind of (-) means that the parameter type cannot be an unboxed tuple, whilst the result type can be anything. Why is this? After reading this documentation I would expect the kind (? - ? - *). Unboxed tuples don't exist. That is, they are in evidence, but they don't actually have any physical representation. The elements of an unboxed tuple are stored in registers when returning from a function, so that the caller can access them immediately (rather than needing to indirect through a pointer to a tuple). ISTR that because of this strategy, there are restrictions on what types of tuples can be unboxed. Theoretically GHC could also allow passing certain arguments in registers when invoking a function, but this isn't supported as yet. -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] ANN: TernaryTrees-0.1.1.1 - An efficient ternary tree implementation of Sets and Maps
Don Stewart wrote: wren: Alex Mason wrote: TernaryTrees is a package that extends Data.Set ad Data.Map with some ternary tree structures, based on the article [http://www.pcplus.co.uk/node/3074/] . For the string (or rather ByteString) version: http://hackage.haskell.org/cgi-bin/hackage-scripts/package/bytestring-trie Which has a number of other significant performance improvements (e.g. node fusion, ByteString instead of String) and a highly expressive interface. Because it uses ByteStrings it can trie any type which can be serialized into a vector of bits[1], albeit indirectly. The real trick with tries is not in just having them[2], it's in having the right interface to make use of what they're good at. For example, if I have multiple tries, I'd like to merge them without doing it element by element[3]. Or if I know I'm going to be making a number of similar queries, it'd be nice if I could cache my position in the trie[4] to avoid repeating the work for the prefixes of all my queries[5]. Using tricks like these leads to significant improvements over using them like hashtables; tries aren't hashtables just like lists aren't arrays. Do you have benchmarks? Somewhere in my email archive (care of Mark Wotton). I'll see if I can dig them up this weekend. The biggest issue here is finding nice datasets (and tasks) to give reasonable benchmarks for. Reading in all of /usr/dict (or the Brown corpus) and looking up all keys only gives one perspective (or two), and not necessarily the most helpful one for real world use. I haven't found any good dataset/task suites like there are for the Language Benchmarks Game, though I'd love to hear about one. The tries /= hashtables comment stems from discussions on various haskell blogs with people inventing their own (or wanting to benchmark Data.Map vs hashtables vs tries vs bloomfilters). As a drop-in replacement tries will perform adequately, but they're nothing overwhelming; the overwhelming comes from changing the usage algorithms to match the stride of the datastructure. I don't think I have links to these discussions anymore to pull up code examples. -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Flipping *-*-* kinds, or monadic finally-tagless madness
You might also look at doing it without all the State monad noise with something like: class Symantics repr where int :: Int - repr Int add :: repr Int - repr Int - repr Int lam :: (repr a - repr b) - repr (a-b) app :: repr (a - b) - repr a - repr b newtype Pretty a = Pretty { runPretty :: [String] - String } pretty :: Pretty a - String pretty (Pretty f) = f vars where vars = [ [i] | i - ['a'..'z']] ++ [i : show j | j - [1..], i - ['a'..'z'] ] instance Symantics Pretty where int = Pretty . const . show add x y = Pretty $ \vars - ( ++ runPretty x vars ++ + ++ runPretty y vars ++ ) lam f = Pretty $ \ (v:vars) - (\\ ++ v ++ . ++ runPretty (f (var v)) vars ++ ) where var = Pretty . const app f x = Pretty $ \vars - ( ++ runPretty f vars ++ ++ runPretty x vars ++ ) -Edward Kmett On Thu, Jul 2, 2009 at 5:52 PM, Kim-Ee Yeoh a.biurvo...@asuhan.com wrote: I'm trying to write HOAS Show instances for the finally-tagless type-classes using actual State monads. The original code: http://okmij.org/ftp/Computation/FLOLAC/EvalTaglessF.hs Two type variables are needed: one to vary over the Symantics class (but only as a phantom type) and another to vary over the Monad class. Hence, the use of 2-variable type constructors. type VarCount = int newtype Y b a = Y {unY :: VarCount - (b, VarCount)} Not knowing of a type-level 'flip', I resort to newtype isomorphisms: newtype Z a b = Z {unZ :: Y b a} instance Monad (Z a) where return x = Z $ Y $ \c - (x,c) (Z (Y m)) = f = Z $ Y $ \c0 - let (x,c1) = m c0 in (unY . unZ) (f x) c1-- Pace, too-strict puritans instance MonadState String (Z a) where get = Z $ Y $ \c - (show c, c) put x = Z $ Y $ \_ - ((), read x) So far so good. Now for the Symantics instances (abridged). class Symantics repr where int :: Int - repr Int -- int literal add :: repr Int - repr Int - repr Int lam :: (repr a - repr b) - repr (a-b) instance Symantics (Y String) where int = unZ . return . show add x y = unZ $ do sx - Z x sy - Z y return $ ( ++ sx ++ + ++ sy ++ ) The add function illustrates the kind of do-sugaring we know and love that I want to use for Symantics. lam f = unZ $ do show_c0 - get let vname = v ++ show_c0 c0 = read show_c0 :: VarCount c1 = succ c0 fz :: Z a String - Z b String fz = Z . f . unZ put (show c1) s - (fz . return) vname return $ (\\ ++ vname ++ - ++ s ++ ) Now with lam, I get this cryptic error message (under 6.8.2): Occurs check: cannot construct the infinite type: b = a - b When trying to generalise the type inferred for `lam' Signature type: forall a1 b1. (Y String a1 - Y String b1) - Y String (a1 - b1) Type to generalise: forall a1 b1. (Y String a1 - Y String b1) - Y String (a1 - b1) In the instance declaration for `Symantics (Y String)' Both the two types in the error message are identical, which suggests no generalization is needed. I'm puzzled why ghc sees an infinite type. Any ideas on how to proceed? -- View this message in context: http://www.nabble.com/Flipping-*-%3E*-%3E*-kinds%2C-or-monadic-finally-tagless-madness-tp24314553p24314553.html Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com. ___ 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] How to declare a Typeless Function
Hi I have a function that swaps rows of an array of double swap :: Array (Int,Int) Double - [Int] - Array (Int,Int) Double I then create a function that swaps rows of arrays of Complex Double swap :: Array (Int, Int) (Complex Double) - [Int] - Array (Int, Int) (Complex Double) In reality the function swap does not care whether its working on a double or a complex number. how do I declare swap so that it will work whether it's a complex or a double array. I tried googling but I wasn't sure what to google. fernan -- http://www.fernski.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] How to declare a Typeless Function
swap :: Array (Int, Int) a - [Int] - Array (Int, Int) a The lowercase a means that that type variable is polymorphic, i.e. it can be any type. Alex On Thu, Jul 2, 2009 at 8:05 PM, Fernan Bolandofernanbola...@mailc.net wrote: Hi I have a function that swaps rows of an array of double swap :: Array (Int,Int) Double - [Int] - Array (Int,Int) Double I then create a function that swaps rows of arrays of Complex Double swap :: Array (Int, Int) (Complex Double) - [Int] - Array (Int, Int) (Complex Double) In reality the function swap does not care whether its working on a double or a complex number. how do I declare swap so that it will work whether it's a complex or a double array. I tried googling but I wasn't sure what to google. fernan -- http://www.fernski.com ___ 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] How to present the commonness of some objects?
Hi, I thought class was for this purpose. But it turns out not. Code as following could not compiled. 1 main = do 2 mapM_ (\(x, y, widget) - do 3a - widgetRun widget 4putStrLn $ show a 5 ) widgetList 6 7 widgetList :: (Widget w) = [(Integer, Integer, w)] 8 widgetList = [] 9 10 class Widget w where 11 widgetRun :: w - IO () --- % ghc --make tmp/test.hs [1 of 1] Compiling Main ( tmp/test.hs, /tmp/Main.o ) tmp/test.hs:3:16: Ambiguous type variable `t' in the constraint: `Widget t' arising from a use of `widgetRun' at tmp/test.hs:3:16-31 Probable fix: add a type signature that fixes these type variable(s) -- 竹密岂妨流水过 山高哪阻野云飞 ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] How to present the commonness of some objects?
You have a couple problems here. The first is that GHC has no idea what particular type 'w' widgetList has, because the empty list is polymorphic. The second is that it looks like you probably want a heterogeneous list of widgets -- that is, possibly different types of widget as long as they all conform to Widget. To do this you'll need ExistentialQuantification (or GADTs I guess?). For example: {-# LANGUAGE ExistentialQuantification #-} class Widget w where widgetRun :: w - IO () data SomeWidget = forall w. Widget w = SomeWidget w widgetList :: [(Integer, Integer, SomeWidget)] widgetList = [] main = mapM aux widgetList aux (x, y, sw) = case sw of SomeWidget w - widgetRun w Note that the type variable for widgetList 'w' has disappeared. Before, with the type variable 'w', all elements of the widgetList had to be of the same type (lists being homogeneous). By wrapping up the type variable 'w' inside SomeWidget, you can now have whatever types of widgets in that SomeWidget, e.g. data Button = Button (IO ()) instance Widget Button where widgetRun = ... data Label = Label (String - IO ()) instance Widget Label where widgetRun = ... widgetList:: [(Integer, Integer, SomeWidget)] widgetList = [ SomeWidget (Button $ putStrLn ding!) , SomeWidget (Label $ putStrLn . (entered: ++)) ] Before, without existential quantification, you had to have all the same type of widget (e.g. all Button or all Label) Hope this makes it more clear. -Ross On Jul 3, 2009, at 12:00 AM, Magicloud Magiclouds wrote: Hi, I thought class was for this purpose. But it turns out not. Code as following could not compiled. 1 main = do 2 mapM_ (\(x, y, widget) - do 3a - widgetRun widget 4putStrLn $ show a 5 ) widgetList 6 7 widgetList :: (Widget w) = [(Integer, Integer, w)] 8 widgetList = [] 9 10 class Widget w where 11 widgetRun :: w - IO () --- % ghc --make tmp/test.hs [1 of 1] Compiling Main ( tmp/test.hs, /tmp/Main.o ) tmp/test.hs:3:16: Ambiguous type variable `t' in the constraint: `Widget t' arising from a use of `widgetRun' at tmp/test.hs: 3:16-31 Probable fix: add a type signature that fixes these type variable(s) -- 竹密岂妨流水过 山高哪阻野云飞 ___ 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] How to present the commonness of some objects?
Wow, this complex Thank you. I will try that. On Fri, Jul 3, 2009 at 12:24 PM, Ross Mellgrenrmm-hask...@z.odi.ac wrote: You have a couple problems here. The first is that GHC has no idea what particular type 'w' widgetList has, because the empty list is polymorphic. The second is that it looks like you probably want a heterogeneous list of widgets -- that is, possibly different types of widget as long as they all conform to Widget. To do this you'll need ExistentialQuantification (or GADTs I guess?). For example: {-# LANGUAGE ExistentialQuantification #-} class Widget w where widgetRun :: w - IO () data SomeWidget = forall w. Widget w = SomeWidget w widgetList :: [(Integer, Integer, SomeWidget)] widgetList = [] main = mapM aux widgetList aux (x, y, sw) = case sw of SomeWidget w - widgetRun w Note that the type variable for widgetList 'w' has disappeared. Before, with the type variable 'w', all elements of the widgetList had to be of the same type (lists being homogeneous). By wrapping up the type variable 'w' inside SomeWidget, you can now have whatever types of widgets in that SomeWidget, e.g. data Button = Button (IO ()) instance Widget Button where widgetRun = ... data Label = Label (String - IO ()) instance Widget Label where widgetRun = ... widgetList:: [(Integer, Integer, SomeWidget)] widgetList = [ SomeWidget (Button $ putStrLn ding!) , SomeWidget (Label $ putStrLn . (entered: ++)) ] Before, without existential quantification, you had to have all the same type of widget (e.g. all Button or all Label) Hope this makes it more clear. -Ross On Jul 3, 2009, at 12:00 AM, Magicloud Magiclouds wrote: Hi, I thought class was for this purpose. But it turns out not. Code as following could not compiled. 1 main = do 2 mapM_ (\(x, y, widget) - do 3 a - widgetRun widget 4 putStrLn $ show a 5 ) widgetList 6 7 widgetList :: (Widget w) = [(Integer, Integer, w)] 8 widgetList = [] 9 10 class Widget w where 11 widgetRun :: w - IO () --- % ghc --make tmp/test.hs [1 of 1] Compiling Main ( tmp/test.hs, /tmp/Main.o ) tmp/test.hs:3:16: Ambiguous type variable `t' in the constraint: `Widget t' arising from a use of `widgetRun' at tmp/test.hs:3:16-31 Probable fix: add a type signature that fixes these type variable(s) -- 竹密岂妨流水过 山高哪阻野云飞 ___ 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