From divisortheory at gmail.com Wed Apr 1 00:16:57 2009 From: divisortheory at gmail.com (Zachary Turner) Date: Wed Apr 1 00:04:08 2009 Subject: [Haskell-beginners] Basic Parsec question Message-ID: <478231340903312116l10982ce7m8f401baf316c6031@mail.gmail.com> Hi, I downloaded the package lispparser to, well, parse lisp code. I really have absolutely no idea what I'm doing though. I can look at the source of the module and see that it's exporting a single data type called LispVal and a single function called parseExpr, so somehow I should be able to pass an arbitrary block of lisp code into this function and get back a LispVal. But for the life of me I can't figure out how. I've looked at the documentation but I get even more confused because it links me to the Parsec documentation which is probably way over my head. Basically I just want a simple function: parse :: String -> LispVal parse expr = ??? presumably by making some use of the exported 'thing' (since I'm not really sure how to interpret its type) parseExpr :: Parser LispVal Thanks for any help -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090331/3f884cb0/attachment.htm From aslatter at gmail.com Wed Apr 1 00:34:16 2009 From: aslatter at gmail.com (Antoine Latter) Date: Wed Apr 1 00:21:28 2009 Subject: [Haskell-beginners] Basic Parsec question In-Reply-To: <478231340903312116l10982ce7m8f401baf316c6031@mail.gmail.com> References: <478231340903312116l10982ce7m8f401baf316c6031@mail.gmail.com> Message-ID: <694519c50903312134y4443cf72q5d0a2be62a56c145@mail.gmail.com> 2009/3/31 Zachary Turner : > Hi, > > I downloaded the package lispparser to, well, parse lisp code.? I really > have absolutely no idea what I'm doing though.? I can look at the source of > the module and see that it's exporting a single data type called LispVal and > a single function called parseExpr, so somehow I should be able to pass an > arbitrary block of lisp code into this function and get back a LispVal.? But > for the life of me I can't figure out how.? I've looked at the documentation > but I get even more confused because it links me to the Parsec documentation > which is probably way over my head.? Basically I just want a simple > function: > > parse :: String -> LispVal > parse expr = ??? > > presumably by making some use of the exported 'thing' (since I'm not really > sure how to interpret its type) > > parseExpr :: Parser LispVal > > Thanks for any help > You should be able to use the function "parse" from the parsec package like so: > parse parseExp "name of source for error reporting" "(some lisp expression") The function "parse" returns a value of type (Either ParseError a), where in this case the type-var 'a' wil be a LispVal. Does that help? Antoine From divisortheory at gmail.com Wed Apr 1 01:50:59 2009 From: divisortheory at gmail.com (Zachary Turner) Date: Wed Apr 1 01:38:09 2009 Subject: [Haskell-beginners] Basic Parsec question In-Reply-To: <694519c50903312134y4443cf72q5d0a2be62a56c145@mail.gmail.com> References: <478231340903312116l10982ce7m8f401baf316c6031@mail.gmail.com> <694519c50903312134y4443cf72q5d0a2be62a56c145@mail.gmail.com> Message-ID: <478231340903312250m356c3694m3f76703e17915d52@mail.gmail.com> On Tue, Mar 31, 2009 at 11:34 PM, Antoine Latter wrote: > You should be able to use the function "parse" from the parsec package like > so: > > > parse parseExp "name of source for error reporting" "(some lisp > expression") > > The function "parse" returns a value of type (Either ParseError a), > where in this case the type-var 'a' wil be a LispVal. > > Does that help? > That was perfect, thanks. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090401/215831d0/attachment.htm From mpm at alumni.caltech.edu Wed Apr 1 02:33:27 2009 From: mpm at alumni.caltech.edu (Michael Mossey) Date: Wed Apr 1 02:20:55 2009 Subject: [Haskell-beginners] Re: making translation from imperative code In-Reply-To: References: <49D21274.80106@alumni.caltech.edu> Message-ID: <49D30AB7.9070909@alumni.caltech.edu> Heinrich Apfelmus wrote: > Michael Mossey wrote: >> I'm translating a Python program into Haskell, and running into a >> problem---a type of code where I don't know how to make the conceptual ... > > Can you elaborate on what exactly the algorithm is doing? Does it just > emit notes/chords/symbols at given positions or does it also try to > arrange them nicely? And most importantly, "where" does it emit them to, > i.e. what's the resulting data structure? > > So far, the problem looks like a basic fold to me. Here is some Haskell code that explains the problem in more detail. ------------------------------------------------------------- ------------------------------------------------------------- -- layoutSystem -------------------------------------------------------------- -------------------------------------------------------------- -- A "system" in musical typesetting terminology is a -- collection of staves that are all played simultaneously; -- that is, they are aligned in time and space. This is a -- simple layout algorithm that uses the concept of -- "chunk"--- a chunk is a set of events (notes, dynamic -- changes, etc.) that occur on a subset of the staves, and -- occur at the same time and therefore need to be aligned -- vertically. Each item has a width and items must be -- placed so they don't overlap. (There is no attempt to -- align them in an aesthetically pleasing way; they simply -- must not collide.) -- -- We presume that something called a "score" exists, which -- is an object representing the underlying music data, from -- which can be extracted a list of chunks, each -- associated with the time at which it is played. We -- don't show the structure of a score here; we just -- assume that we can operate on a score via two -- functions: -- -- A function to grab a chunk: -- scoreGetChunkData :: Score -> Time -> ChunkData -- A function to get time of next chunk: -- scoreNextTime :: Score -> Time -> Time -- -- This basic structure of this algorithm is a loop with state. -- Here's the state. -- 'time' :: Double -- is the time of next chunk to layout. -- 'staffLayouts' :: [( String, StaffLayout)] -- is an -- association list of staff names and StaffLayout -- objects. Each StaffLayout object accumulates the chunks -- that belong to that staff. -- 'val' :: Int -- This is the next x-position that is -- available for placing a new chunk (this -- is an abbreviation for vertical -- alignment line). -- 'chunkDataMem' This is a cache or memory of all chunks -- we have encountered in this system, for -- lookup later. data SystemLayoutState = SystemLayoutState { time :: Double, staffLayouts :: [ ( String, StaffLayout ) ], val :: Int, chunkDataMem :: [ ChunkData ] } layoutSystem Double -> Score -> Int -> Config -> SystemLayoutState layoutSystem firstTime score rightBorder config = -- Work is done by helper function layoutSystem', -- after giving it the initial state. layoutSystem' initialState -- Construct initial state. where initialState = SystemLayoutState { time = firstTime, staffLayouts = [], val = getConfig config "prefixWidth", storedChunkData = [] } -- Define the helper function layoutSystem' layoutSystem' :: SystemLayoutState -> SystemLayoutState layoutSystem' state = -- Get ChunkData from the score at the time -- associated with the current state. let chunkData = scoreGetChunkData score (time state) -- Call 'incorporateChunkData' to try to add -- it to the score. This will return a -- tuple, the first member being the status -- (True means we can add no more chunks -- because we ran out of horizontal space) -- and the second is updated state. case incorporateChunkData state chunkData rightBorder of ( True, state' ) -> state' ( False, state' ) -> tryAgain state' -- We separate the definition of tryAgain just to make -- the structure of this whole function a little -- clearer. tryAgain asks the score for the next -- time at which a chunk exists. In the case there -- *are no more* chunks, it terminates the -- recursion, while also modifying the state in -- some way to communicate that the recursion -- terminated *because of running out of chunks* -- instead of running out of horizontal -- space. Otherwise it calls back to layoutSystem'. tryAgain state = case scoreNextTime score (time state) of -1 -> indicateNoMoreChunks state t -> layoutSystem' (setTime state t) From mpm at alumni.caltech.edu Wed Apr 1 20:45:29 2009 From: mpm at alumni.caltech.edu (Michael P Mossey) Date: Wed Apr 1 20:32:40 2009 Subject: [Haskell-beginners] short function to remove and replace an item Message-ID: <49D40AA9.8070001@alumni.caltech.edu> What if I have a list xs, and I want to remove one item and replace it with another? The item to remove can be detected by a predicate function. The order of the items doesn't matter. How about this: replaceItem :: (a -> Bool) -> a -> [a] -> [a] replaceItem p new xs = new : snd (partition p xs) This will actually replace all items that match the predicate with one copy of 'new'. It will also prepend 'new' even if no items match the predicate. For another challenge, can someone explain to me how to write this in point-free style? Thanks, Mike From vss at 73rus.com Wed Apr 1 21:01:55 2009 From: vss at 73rus.com (Vlad Skvortsov) Date: Wed Apr 1 20:48:53 2009 Subject: [Haskell-beginners] short function to remove and replace an item In-Reply-To: <49D40AA9.8070001@alumni.caltech.edu> References: <49D40AA9.8070001@alumni.caltech.edu> Message-ID: <49D40E83.5070604@73rus.com> Prelude> let replaceItem p n = map (\x -> if p x then n else x) Prelude> replaceItem odd 100 [1..10] [100,2,100,4,100,6,100,8,100,10] Michael P Mossey wrote: > What if I have a list xs, and I want to remove one item and replace it > with another? The item to remove can be detected by a predicate > function. The order of the items doesn't matter. How about this: > > replaceItem :: (a -> Bool) -> a -> [a] -> [a] > replaceItem p new xs = new : snd (partition p xs) > > This will actually replace all items that match the predicate with one > copy of 'new'. It will also prepend 'new' even if no items match the > predicate. > > For another challenge, can someone explain to me how to write this in > point-free style? -- Vlad Skvortsov, vss@73rus.com, http://vss.73rus.com From daniel.is.fischer at web.de Wed Apr 1 21:38:40 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Wed Apr 1 21:25:53 2009 Subject: [Haskell-beginners] short function to remove and replace an item In-Reply-To: <49D40AA9.8070001@alumni.caltech.edu> References: <49D40AA9.8070001@alumni.caltech.edu> Message-ID: <200904020338.41194.daniel.is.fischer@web.de> Am Donnerstag 02 April 2009 02:45:29 schrieb Michael P Mossey: > What if I have a list xs, and I want to remove one item and replace it > with another? The item to remove can be detected by a predicate > function. The order of the items doesn't matter. How about this: From the description, I'd rather have expected something like replaceItem :: (a -> Bool) -> a -> [a] -> [a] replaceItem p new (x:xs) | p x = new : xs -- or new : replaceItem p new xs | otherwise = x : replaceItem p new xs replaceItem _ _ [] = [] which could also be nicely written as replaceItem p new xs = case break p xs of (front,_:back) -> front ++ new : back _ -> xs the multiple replace: map (\x -> if p x then new else x) xs > > replaceItem :: (a -> Bool) -> a -> [a] -> [a] > replaceItem p new xs = new : snd (partition p xs) This could also be written as replaceItem p new xs = new : filter (not . p) xs > > This will actually replace all items that match the predicate with one > copy of 'new'. It will also prepend 'new' even if no items match the > predicate. > > For another challenge, can someone explain to me how to write this in > point-free style? replaceItem p new xs = new : snd (partition p xs) rewrite the right hand side as (new :) . snd . (partition p) $ xs Now you can drop the last argument (xs) replaceItem p new = (new :) . snd . partition p To move new to the end, rewrite the right hand side as ((:) new) . (snd . partition p) === (. (snd . partition p)) . (:) $ new Now you can drop the next parameter, new: replaceItem p = (. (snd . partition p)) . (:) To move the predicate p to the end, rewrite the right hand side as (.) (. (snd . partition p)) (:) === flip (.) (:) (. (snd . partition p)) === flip (.) (:) $ flip (.) (snd . partition p) === flip (.) (:) $ flip (.) ((snd .) . partition $ p) === flip (.) (:) . flip (.) $ ((snd .) . partition $ p) === flip (.) (:) . flip (.) . (snd .) . partition $ p Now you can drop the last parameter, p: replaceItem = flip (.) (:) . flip (.) . (.) snd . partition Prelude Data.List> let replaceItem = flip (.) (:) . flip (.) . (.) snd . partition in replaceItem even 7 [1 .. 20] [7,1,3,5,7,9,11,13,15,17,19] But please, don't write your code in that style. Getting rid of xs is fine, dropping new leads to hard to read code. Removing all arguments is sheer obfuscation. There's more to writing pointfree code than being able to, one must also know when to stop. > > Thanks, > Mike Cheers, Daniel From divisortheory at gmail.com Wed Apr 1 22:50:04 2009 From: divisortheory at gmail.com (Zachary Turner) Date: Wed Apr 1 22:37:13 2009 Subject: [Haskell-beginners] short function to remove and replace an item In-Reply-To: <49D40AA9.8070001@alumni.caltech.edu> References: <49D40AA9.8070001@alumni.caltech.edu> Message-ID: <478231340904011950p23aaf381w8a5a891545f2c9b5@mail.gmail.com> On Wed, Apr 1, 2009 at 7:45 PM, Michael P Mossey wrote: > What if I have a list xs, and I want to remove one item and replace it with > another? The item to remove can be detected by a predicate function. The > order of the items doesn't matter. How about this: > > replaceItem :: (a -> Bool) -> a -> [a] -> [a] > replaceItem p new xs = new : snd (partition p xs) > > This will actually replace all items that match the predicate with one copy > of 'new'. It will also prepend 'new' even if no items match the predicate. > > For another challenge, can someone explain to me how to write this in > point-free style? > I used an intermediate helper function, but the replaceItem function is point free choose :: (a -> Bool) -> (a -> b) -> (a -> b) -> a -> b choose pred yes _ val | (pred val) = yes val choose _ _ no val = no val replaceItem :: (a -> Bool) -> a -> [a] -> [a] replaceItem pred rep = map (choose pred id (const rep)) -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090401/aa44421e/attachment.htm From divisortheory at gmail.com Wed Apr 1 23:03:09 2009 From: divisortheory at gmail.com (Zachary Turner) Date: Wed Apr 1 22:50:18 2009 Subject: [Haskell-beginners] short function to remove and replace an item In-Reply-To: <478231340904011950p23aaf381w8a5a891545f2c9b5@mail.gmail.com> References: <49D40AA9.8070001@alumni.caltech.edu> <478231340904011950p23aaf381w8a5a891545f2c9b5@mail.gmail.com> Message-ID: <478231340904012003k3c24f2e3w5c718c5a6e42b632@mail.gmail.com> On Wed, Apr 1, 2009 at 9:50 PM, Zachary Turner wrote: > > > On Wed, Apr 1, 2009 at 7:45 PM, Michael P Mossey wrote: > >> What if I have a list xs, and I want to remove one item and replace it >> with another? The item to remove can be detected by a predicate function. >> The order of the items doesn't matter. How about this: >> >> replaceItem :: (a -> Bool) -> a -> [a] -> [a] >> replaceItem p new xs = new : snd (partition p xs) >> >> This will actually replace all items that match the predicate with one >> copy of 'new'. It will also prepend 'new' even if no items match the >> predicate. >> >> For another challenge, can someone explain to me how to write this in >> point-free style? >> > > I used an intermediate helper function, but the replaceItem function is > point free > > choose :: (a -> Bool) -> (a -> b) -> (a -> b) -> a -> b > choose pred yes _ val | (pred val) = yes val > choose _ _ no val = no val > > replaceItem :: (a -> Bool) -> a -> [a] -> [a] > replaceItem pred rep = map (choose pred id (const rep)) > Ok I looked at the OP again and apparently I didn't understand the wording of the question :P I just thought it said to replace each element in the list that matched the predicate with the new item. How about this? replaceItem :: [a] -> (a -> Bool) -> a -> [a] let replaceItem xs pred = (: filter (not.pred) xs) Note that I changed the order of the arguments, the value now comes last. But I think this still should be ok? -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090401/fec35904/attachment.htm From apfelmus at quantentunnel.de Thu Apr 2 01:30:27 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Thu Apr 2 01:17:52 2009 Subject: [Haskell-beginners] Re: making translation from imperative code In-Reply-To: <49D30AB7.9070909@alumni.caltech.edu> References: <49D21274.80106@alumni.caltech.edu> <49D30AB7.9070909@alumni.caltech.edu> Message-ID: Michael Mossey wrote: > Heinrich Apfelmus wrote: >> >> Can you elaborate on what exactly the algorithm is doing? Does it just >> emit notes/chords/symbols at given positions or does it also try to >> arrange them nicely? And most importantly, "where" does it emit them to, >> i.e. what's the resulting data structure? >> >> So far, the problem looks like a basic fold to me. > > Here is some Haskell code that explains the problem in > more detail. > [...] Thanks for the elaboration. I think the code doesn't separate concerns very well; mixing information about widths and times, page size and the recursion itself into one big gnarl. Also, there is one important issue, namely returning a special value like -1 as error code in > tryAgain state = > case scoreNextTime score (time state) of > -1 -> indicateNoMoreChunks state > t -> layoutSystem' (setTime state t) Don't do this, use Maybe instead tryAgain state = case scoreNextTime score (time state) of Nothing -> indicateNoMoreChunks state Just t -> layoutSystem' (state { time = t }) where Nothing indicates failure and Just success. Back to the gnarl in general, I still don't have a good grasp on the problem domain, which is key to structuring the algorithm. Therefore, I'll expand on toy model and you tell me how it differs from the real thing. The model is this: we are given several lists of notes (f.i. a piano part and a vocal line) where each note is annotated with the time it is to be played at. We abstract away the fact that we are dealing with musical notes and simply consider a list of *events* type Time = Integer type Events a = [(Time, a)] with the invariant that the timestamps are (strictly) increasing: valid :: Events a -> Bool valid xs = all $ zipWith (\(t1,_) (t2,_) -> t1 < t2) xs (drop 1 xs) Now, the toy task is to merge several lists of similar events into one big list that is ordered by time as well. merge :: [Events a] -> Events [a] Since some events may now occur simultaneously, the events of the results are actually lists of "primitive" events. One possibility for implementing merge is to start with a function to merge two event lists merge2 :: Events [a] -> Events [a] -> Events [a] merge2 [] ys = ys merge2 xs [] = xs merge2 xs@((tx,x):xt) ys@((ty,y):yt) = case compare tx ty of LT -> (tx,x ) : merge2 xt ys EQ -> (tx,x++y) : merge2 xt yt GT -> (ty, y) : merge2 xs yt and to apply it several times merge = foldr merge2 [] . map lift where lift = map $ \(t,x) -> (t,[x]) Another possibility is to simply concatenate everything first and then sort by time merge = map (\((t,x):xs) -> (t,x:map snd xs)) . groupBy ((==) `on` fst) . sortBy (comparing fst) . concat The code above can be made more readable by choosing nice names like time = fst event = snd or avoiding pairs altogether and implementing these names as record fields. Also, the (&&&) combinator from Control.Arrow is very handy. merge = map (time . head &&& map event) . groupBy ((==) `on` time) . sortBy (comparing time) . concat I hope this gives you a few ideas to think about. How does this toy model differ from the real thing? Regards, apfelmus PS: If some parts of my example code give you trouble, it's probably fastest to ask around on the #haskell IRC channel. -- http://apfelmus.nfshost.com From divisortheory at gmail.com Thu Apr 2 02:34:04 2009 From: divisortheory at gmail.com (Zachary Turner) Date: Thu Apr 2 02:21:13 2009 Subject: [Haskell-beginners] Can we make this program better (and shorter)? Message-ID: <478231340904012334s4283de84j78138ed032aef0bd@mail.gmail.com> Be warned, this code is really ugly. I need some help to make it better. I was in this situation this week where there was a sample of some numbers. I knew the valid possible range that numbers could lie in, and I knew about 30% of the actual values from the sample. I also knew the original average and the original standard deviation. I wanted more information about the other values in the sample, so I sat down and derived two formulas: One that, given an average, the number of items in the average, and 1 number that you know was used somewhere in the calculation of the average, calculates what the average would be if that number had not been there. Another that does the same for standard deviation. The second formula is fairly insane, if someone can figure out how to simplify it let me know, it took forever to derive it without making any mistakes. Actually I didn't even know it was possible to do a running standard deviation like that until I sat down and derived it. So anyway the program asks the user how large the original sample was, and the average and standard deviation. Then it runs in a loop asking it for a value to remove from the sample set and calculate the updated values. For certain values however, even if they are actually in the range of valid values for the range of the sample space, they might be impossible to achieve given a certain sample size, average, and stdev (for example, if you have two numbers in the range [0..100] and the average is 100, and you remove 1 number, none of the remaining numbers can be 0 obviously). So I wanted to detect this if the user inputs such a value, that way for one thing I can calculate exact upper and lower bounds for the actual range of the numbers just by trying all possible values. I know that the nature of the program mandates that there's going to be a lot of IO Monadic code, but I still feel like my code sucks. For one thing, I really tried to make the removePoints method be pure, and just accept a list as the argument and do the I/O in another function. I imagined some kind of lazy list comprehension, where each time the removePoints method asked for the next item, it would ask for the input and do all that stuff. I couldn't figure out how to make this work. Perhaps it's not even possible, since by definition a list comprehension that asked for input when forced isn't pure. But I still think there's a better way to do it. I also really dislike having to do manual recursion for getting input, there's got to be a way to use lists and built-in functions to do it for you, using some kind of takeWhile() perhaps. Anyway if anyone has any suggestions for making this code look better, more elegant, or more Haskelly, let me know :) import Control.Arrow promptUntilValid :: (Read a, Show a, Eq a) => String -> IO a promptUntilValid prompt = do putStr prompt putStr " " result <- getLine case (reads result) of [(parsed,_)] -> return parsed invalid -> do putStrLn $ "Invalid input! You entered " ++ result ++ ", and results length is " ++ (show (length invalid)) promptUntilValid prompt newStdev :: Int -> (Int,Int,Double,Double,Double) -> Double newStdev removeValue (old_count, new_count, old_stdev, old_avg, new_avg) = sqrt.(/ (n-1.0)) $ n * ?_x^2 + 2.0*old_avg*new_avg*(n-1.0) - (n-1.0)*old_avg^2 - (a_n - old_avg)^2 - (n-1.0)*new_avg^2 where ?_x = old_stdev n = fromIntegral old_count a_n = fromIntegral removeValue removeSinglePoint :: Int -> (Int,Double,Double) -> (Int,Double,Double) removeSinglePoint value (count,stdev,avg) = (new_count,new_stdev,new_avg) where new_count = count-1 new_avg = (avg*(fromIntegral count) - (fromIntegral value)) / (fromIntegral new_count) new_stdev = newStdev value (count, new_count, stdev, avg, new_avg) removePoints :: (Int,Double,Double) -> IO () removePoints (count,stdev,avg) = do putStr "Enter a number to remove from the sample set (Enter to stop): " putStr " " result <- getLine case (result,reads result) of ("",_) -> return () (_, [(parsed,_)]) -> do if (any (uncurry (||) . (isInfinite &&& isNaN)) [new_stdev, new_avg]) then do putStrLn "That number could not have been there! The new values are NaN!" removePoints (count,stdev,avg) else do putStrLn $ "New count: " ++ (show new_count) ++ ", new stdev: " ++ (show new_stdev) ++ ", new avg: " ++ (show new_avg) removePoints (new_count,new_stdev,new_avg) where (new_count,new_stdev,new_avg) = removeSinglePoint parsed (count,stdev,avg) (_,invalid) -> do putStrLn $ "Invalid input! You entered " ++ result ++ ", and results length is " ++ (show (length invalid)) removePoints (count,stdev,avg) main = do num_values::Int <- promptUntilValid "Enter the initial number of values: " stdev::Double <- promptUntilValid "Enter the initial standard deviation: " average::Double <- promptUntilValid "Enter the initial average: " putStrLn ("num_values = " ++ (show num_values)) putStrLn ("stdev = " ++ (show stdev)) putStrLn ("average = " ++ (show average)) removePoints (num_values, stdev, average) return () -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090402/2f361ee4/attachment-0001.htm From mpm at alumni.caltech.edu Thu Apr 2 07:33:05 2009 From: mpm at alumni.caltech.edu (Michael Mossey) Date: Thu Apr 2 07:20:31 2009 Subject: [Haskell-beginners] Re: making translation from imperative code In-Reply-To: References: <49D21274.80106@alumni.caltech.edu> <49D30AB7.9070909@alumni.caltech.edu> Message-ID: <49D4A271.9080201@alumni.caltech.edu> Heinrich Apfelmus wrote: > Michael Mossey wrote: >> Heinrich Apfelmus wrote: >>> Can you elaborate on what exactly the algorithm is doing? Does it just >>> emit notes/chords/symbols at given positions or does it also try to >>> arrange them nicely? And most importantly, "where" does it emit them to, >>> i.e. what's the resulting data structure? >>> >>> So far, the problem looks like a basic fold to me. >> Here is some Haskell code that explains the problem in >> more detail. >> [...] > > Thanks for the elaboration. > > I think the code doesn't separate concerns very well; mixing information > about widths and times, page size and the recursion itself into one big > gnarl. > > Also, there is one important issue, namely returning a special value > like -1 as error code in > >> tryAgain state = >> case scoreNextTime score (time state) of >> -1 -> indicateNoMoreChunks state >> t -> layoutSystem' (setTime state t) > > Don't do this, use Maybe instead > > tryAgain state = case scoreNextTime score (time state) of > Nothing -> indicateNoMoreChunks state > Just t -> layoutSystem' (state { time = t }) > > where Nothing indicates failure and Just success. Okay, tried to give some more detail. thanks for the interesting code. I will study it some more. But here's the original task. {- A composition consists of several voices or instruments, each indicated by its own *staff*. Visually, a staff is a layout of items such as notes, clef signs, and accidentals arranged horizontally from left to right in increasing time. A *system* is a set of staves stacked vertically that represent instruments playing at the same time. Here is a simple representation of a system, in which the pipe character represents items. Note that some of the items are aligned vertically meaning they will play at the same time. At other times, only one staff contains a sounding item. staff 1: | | | | staff 2: | | | | Next we elaborate this model to show that items have visual width. Here they are represented by clusters of x's with a pipe in the middle. The pipe represents the part of the item that needs to be aligned with items on other staves. For example, in the visual representation of a chord, the part of the chord called the notehead needs to be aligned with noteheads on other staves. (A chord includes other symbols, like accidentals and flags, which get drawn to the right or left of the notehead and don't need to be aligned vertically with anything else.) staff 1: x|x xx|xx x|x staff 2: x|x x|x xxxxx|xxxxx a b c d Here you can see that there is an additional constraint on layout, which is that items need to have horizontal space around them so they don't collide. For instance, the very wide item at 'd' (on staff 2) means that the item on staff 1 at 'd' has to be positioned far to the right of its previous item. Note that data exists in two domains: there is data that describes notes; that is, pitches and timbres and volumes and times and duration. We'll call this the 'score'. It's the fundamental data. Then there is the visual *representation* of the score. Here we are concerned only with creating a visual representation. However, we need to refer to data in the score. -} -- LayoutItem is a visual representation of a note. The center of the note -- or chord (specifically the part that needs to be aligned vertically) -- goes at position 'pos', the other variables describe how much the -- note sticks out to the left, right, top, and bottom. We omit other -- details about the note. data LayoutItem = LayoutItem { pos :: ( Int, Int ), leftWidth, rightWidth, topHeight, bottomHeight :: Int, staffId :: String } -- ChunkData is 'score' domain data. It represents all notes that start -- sounding at the same time. It is an association list of staff -- names to notes. Note that a complete score is essentially a list of -- chunks in time order. data ChunkData = ChunkData [ ( String, [ Note ] ) ] -- We'll just say a note is an int giving its pitch. type Note = Int -- A system layout is a set of *staves*. Here, staves are -- lists of LayoutItem, put into an association list by staff name. -- There is also a need to make a memo of chunks for future reference. data SystemLayout = SystemLayout { staves :: [ ( String, [ LayoutItem ] ) ], chunkMemo :: [ ChunkData ] } -- This is the loop state. During the loop, 'time' keeps advancing to -- the time of the next chunk, and 'nextX' keeps advancing to the next -- vetical alignment location. data LoopState = LoopState { time :: Double, nextX :: Int } --- Details of score omitted, but assume it has two key functions. data Score = Score ... scoreGetChunkData :: Score -> Time -> ChunkData scoreNextTime :: Score -> Time -> Maybe Time -- layoutSystem works as follows: it takes a time to start the layout -- at, a score, and a maximum paper width, and returns a tuple with the -- LoopState and SystemLayout at termination. -- -- The looping happens in the helper function layoutSystem' which -- has a simple signature: basically all relevant state goes in, -- and all relevant state comes out. (See signtaure below.) -- -- incororateChunkData does the main work of looking at all notes -- in the next chunk and either finguring out how to add them to -- the staves, or indicating they can't be added without going off -- the right edge of the paper. It returns -- a tuple ( Bool, LoopState, SystemLayout ) where the Bool indicates -- success or failure. layoutSystem Time -> Score -> Int -> ( LoopState, SystemLayout ) layoutSystem firstTime score maxWidth = layoutSystem' initialState initialSystemLayout where initialState = LoopState { time = firstTime, nextX = 0 } initialSystemLayout SystemLayout { staves = [], chunkMem = [] } ) layoutSystem' :: LoopState -> SystemLayout ->( LoopState, SystemLayout ) layoutSystem' state slayout = let chunkData = scoreGetChunkData score (time state) in case incorporateChunkData chunkData state slayout maxWidth of ( True, state', slayout' ) -> layoutSystem' state' slayout' ( False, state', slayout') -> case scoreNextTime score (time state) of Just t -> layoutSystem' state' { time = t } slayout' Nothing -> ( state', slayout' ) -- incorporateChunkData is a function that does the work of looking at -- all notes -- in the next chunk and either figuring out how to add them to -- the staves, or indicating they can't be added without going off -- the right edge of the paper. It returns -- a tuple ( Bool, LoopState, SystemLayout ) where the Bool indicates -- success or failure. incorporateChunkData :: LoopState -> SystemLayout -> Int -> ( Bool, LoopState, SystemLayout ) incorporateChunkData chunkData state slayout maxWidth = let items = makeLayoutItems chunkData -- Find new x alignment value, which done by finding how far right -- each item needs to go to avoid collision with previous items -- For each staff staffId and each item i that needs to be added to -- the staff, the question is: how far right does the staff extend, -- and how far left does the new item stick out from its central -- position? That tells you where the new item needs to go. -- (the function rightExtent finds how far right a staff extends), -- This process needs to be repeated for all staves, noting the -- needed alignment point for each---and then the final determination -- is the maximum of all those alignment points. alignX = max (map (\i -> let r = rightExtent slayout (staffId i) in r + leftWidth i) items) -- Now see if we've run off the right edge of the paper. -- Then check how far to the right each item will extend and -- compare to maxWidth farRight = max ( map (\i -> alignX + rightWidth i) items) if farRight < maxWidth then let slayout' = addItems slayout items alignX state' = state { nextX = alignX + 1 } in ( True, state', slayout' ) else ( False, state, slayout ) From mpm at alumni.caltech.edu Thu Apr 2 08:08:31 2009 From: mpm at alumni.caltech.edu (Michael Mossey) Date: Thu Apr 2 07:55:58 2009 Subject: [Haskell-beginners] the equivalent of OO class data and methods Message-ID: <49D4AABF.6020607@alumni.caltech.edu> I'm making the transition from OO to Haskell, and a major problem for me is that I'm used to OO, where member variables are distinct from other variables and functions, so I can use totally generic member variable names and never have a conflict with other member variables or local variables. For example, if I want to create LayoutItem and name its coordinates x and y, I do this: (Python) class LayoutItem : def __init__( self, x, y ) : self.x, self.y = (x, y ) Then later, p = LayoutItem( 10, 20 ) Then later I can refer to p.x and p.y. I can also create other classes and name *their* member variables x and y, with no confusion. Now, I know that in Haskell I can do data LayoutItem = LayoutItem { x, y :: Int } Later, let p = LayoutItem { x = 10, y = 20 } I have read that this automatically creates "accessor" functions called x and y, so I can refer to (x p) and (y p) let foo = (x p)^2 + (y p)^2 Now let's say I create another type that also uses x and y: data Notehead = Notehead { x, y :: Int } n = Notehead { x = 100, y = 200 } This doesn't work. Apparently the accessor functions x and y (for LayoutItem) have global scope and conflict with those for Notehead. Which means I have to name them different things, which is awkward. For example, data LayoutItem = LayoutItem { layoutItemX, layoutItemY :: Int } data Notehead = Notehead { noteheadItemX, noteheadItemY :: Int } Also, I tried using some of these accessor function names as variables, and the compiler doesn't distinguish between them. For example, myfunc :: Notehead -> LayoutItem -> Int myfunc n p = let layoutItemY = layoutItemX p z = layoutItemY n in z^2 This doesn't work, because declaring layoutItemY as a variable hides its defintion as an accessor function. Is there a way to get what I want from Haskell? Thanks, Mike From gale at sefer.org Thu Apr 2 14:35:26 2009 From: gale at sefer.org (Yitzchak Gale) Date: Thu Apr 2 14:22:49 2009 Subject: [Haskell-beginners] the equivalent of OO class data and methods In-Reply-To: <49D4AABF.6020607@alumni.caltech.edu> References: <49D4AABF.6020607@alumni.caltech.edu> Message-ID: <2608b8a80904021135w1543ee67t164c854a9936d5da@mail.gmail.com> Michael Mossey wrote: > For example, if I want to create LayoutItem and name its coordinates x and > y... > Then later I can refer to p.x and p.y. > I can also create other classes and name *their* member variables x and y, > with no confusion. There are two ways to share names in Haskell. One way, which is most similar to the OO approach, is to use encapsulation. Haskell uses modules for encapsulation and namespace control. However, GHC currently requires each module to reside in a separate source file (even though that is not required by the standard). When you use this method, you need to use dotted names to qualify them, as in your OO example. If only one version of a name is used in a given module, you can choose to import that name unqualified into the namespace of that module. The other approach is using the class system: class Coordinates a where x :: a -> Int y :: a -> Int data LayoutItem = LayoutItem { layoutItemX, layoutItemY :: Int } instance Coordinates LayoutItem where x = layoutItemX y = layoutItemY data Notehead = Notehead { noteheadItemX, noteheadItemY :: Int } instance Coordinates Notehead where x = NoteheadX y = NoteheadY Note that using this approach, the types of x and y always need to have exactly the same shape: a -> Int, where a is the type for which you are declaring the class instance. You can't use Int for one type and Float for another, for example. You can get around that restriction using Haskell extensions such as type families, or multiparameter classes and functional dependencies. With the approach, you do not qualify the names. You just re-use the names, and the type checker figures out what you mean from the context. In case of ambiguity, you use explicit type signatures to clarify the situation. Hope this helps, Yitz From mpm at alumni.caltech.edu Thu Apr 2 14:59:20 2009 From: mpm at alumni.caltech.edu (Michael Mossey) Date: Thu Apr 2 14:46:41 2009 Subject: [Haskell-beginners] CORRECTED: making translation from imperative code] Message-ID: <49D50B08.4080707@alumni.caltech.edu> STOP THE PRESSES--- I noticed some goofs (more late-night programming... ) Corrected below. Read this version. {- A composition consists of several voices or instruments, each indicated by its own *staff*. Visually, a staff is a layout of items such as notes, clef signs, and accidentals arranged horizontally from left to right, representing increasing time. A *system* is a set of staves stacked vertically that represent instruments playing at the same time. Here is a simple representation of a system, in which the pipe character represents items. Note that some of the items are aligned vertically meaning they will play at the same time. At other times, only one staff contains a note. staff 1: | | | | staff 2: | | | | Next we elaborate this model to show that items have visual width. Here they are represented by clusters of x's with a pipe in the middle. The pipe represents the part of the item that needs to be aligned with items on other staves. For example, in the visual representation of a chord, the part of the chord called the notehead needs to be aligned with noteheads on other staves. (A chord includes other symbols, like accidentals and flags, which get drawn to the right or left of the notehead and don't need to be aligned vertically with anything else.) staff 1: x|x xx|xx x|x staff 2: x|x x|x xxxxx|xxxxx a b c d Here you can see that there is an additional constraint on layout, which is that items need to have horizontal space around them so they don't collide. For instance, the very wide item at 'd' (on staff 2) means that the item on staff 1 at 'd' has to be positioned far to the right of its previous item. Note that data exists in two domains: there is data that describes notes; that is, pitches and timbres and volumes and times and duration. We'll call this the 'score'. It's the fundamental data. Then there is the visual *representation* of the score. Here we are concerned only with creating a visual representation. However, we need to refer to data in the score. -} -- LayoutItem is a visual representation of a note. The center of the note -- or chord (specifically the part that needs to be aligned vertically) -- goes at position 'pos', the other variables describe how much the -- note sticks out to the left, right, top, and bottom. We omit other -- details about the note. data LayoutItem = LayoutItem { pos :: ( Int, Int ), leftWidth, rightWidth, topHeight, bottomHeight :: Int, staffId :: String } -- ChunkData is 'score' domain data. It represents all notes that start -- sounding at the same time. It is an association list of staff -- names to notes. Note that a complete score is essentially a list of -- chunks in time order. data ChunkData = ChunkData [ ( String, [ Note ] ) ] -- We'll just say a note is an int giving its pitch. type Note = Int -- A system layout is a set of *staves*. Here, staves are -- lists of LayoutItem, put into an association list by staff name. -- There is also a need to make a memo of chunks for future reference. data SystemLayout = SystemLayout { staves :: [ ( String, [ LayoutItem ] ) ], chunkMemo :: [ ChunkData ] } -- This is the loop state. During the loop, 'time' keeps advancing to -- the time of the next chunk, and 'nextX' keeps advancing to the next -- vetical alignment location. data LoopState = LoopState { time :: Double, nextX :: Int } --- Details of score omitted, but assume it has two key functions. data Score = Score ... scoreGetChunkData :: Score -> Time -> ChunkData scoreNextTime :: Score -> Time -> Maybe Time -- layoutSystem works as follows: it takes a time to start the layout -- at, a score, and a maximum paper width, and returns a tuple with the -- LoopState and SystemLayout at termination. -- -- The looping happens in the helper function layoutSystem' which -- has a simple signature: basically all relevant state goes in, -- and all relevant state comes out. (See signtaure below.) -- -- incororateChunkData does the main work of looking at all notes -- in the next chunk and either finguring out how to add them to -- the staves, or indicating they can't be added without going off -- the right edge of the paper. It returns -- a tuple ( Bool, LoopState, SystemLayout ) where the Bool indicates -- success or failure. layoutSystem Time -> Score -> Int -> ( LoopState, SystemLayout ) layoutSystem firstTime score maxWidth = layoutSystem' initialState initialSystemLayout where initialState = LoopState { time = firstTime, nextX = 0 } initialSystemLayout SystemLayout { staves = [], chunkMem = [] } ) layoutSystem' :: LoopState -> SystemLayout ->( LoopState, SystemLayout ) layoutSystem' state slayout = let chunkData = scoreGetChunkData score (time state) in case incorporateChunkData chunkData state slayout maxWidth of ( False, state', slayout' ) -> ( state, slayout ) ( True, state', slayout') -> case scoreNextTime score (time state') of Just t -> layoutSystem' state' { time = t } slayout' Nothing -> ( state', slayout' ) -- incorporateChunkData is a function that does the work of looking at -- all notes -- in the next chunk and either figuring out how to add them to -- the staves, or indicating they can't be added without going off -- the right edge of the paper. It returns -- a tuple ( Bool, LoopState, SystemLayout ) where the Bool indicates -- success or failure. incorporateChunkData :: LoopState -> SystemLayout -> Int -> ( Bool, LoopState, SystemLayout ) incorporateChunkData chunkData state slayout maxWidth = let items = makeLayoutItems chunkData -- Find new x alignment value, which done by finding how far right -- each item needs to go to avoid collision with previous items. -- For each staff 'staffId' and each item 'i' that needs to be added to -- the staff, the question is: how far right does the staff extend, -- and how far left does the new item stick out from its central -- position? That tells you where the new central position needs to go. -- (the function rightExtent finds how far right a staff extends), -- This process needs to be repeated for all staves, noting the -- needed alignment point for each---and then the final determination -- is the maximum of all those alignment points. alignX = max (map (\i -> let r = rightExtent slayout (staffId i) in r + leftWidth i) items) -- Now see if we've run off the right edge of the paper. -- Then check how far to the right each item will extend and -- compare to maxWidth farRight = max ( map (\i -> alignX + rightWidth i) items) if farRight < maxWidth then let slayout' = addItems slayout items alignX state' = state { nextX = alignX + 1 } in ( True, state', slayout' ) else ( False, state, slayout ) _______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners From mpm at alumni.caltech.edu Thu Apr 2 16:38:27 2009 From: mpm at alumni.caltech.edu (Michael P Mossey) Date: Thu Apr 2 16:25:34 2009 Subject: [Haskell-beginners] the equivalent of OO class data and methods In-Reply-To: <2608b8a80904021135w1543ee67t164c854a9936d5da@mail.gmail.com> References: <49D4AABF.6020607@alumni.caltech.edu> <2608b8a80904021135w1543ee67t164c854a9936d5da@mail.gmail.com> Message-ID: <49D52243.5090905@alumni.caltech.edu> Thanks. One question: Yitzchak Gale wrote: > > One way, which is most similar to the OO approach, is to use > encapsulation. > The other approach is using the class system: > > class Coordinates a where > x :: a -> Int > y :: a -> Int > > data LayoutItem = LayoutItem { layoutItemX, layoutItemY :: Int } > > instance Coordinates LayoutItem where > x = layoutItemX > y = layoutItemY > > data Notehead = Notehead { noteheadItemX, noteheadItemY :: Int } > > instance Coordinates Notehead where > x = NoteheadX > y = NoteheadY > In this case, do local variables still shadow or hide the functions contained by the class? In other words, would this work? foo :: LayoutItem -> Notehead -> Int foo l n = let y = x l + x n z = y l + y n in z + y I'm guessing that the variable y will shadow the function y. This is a problem, because I want generic names available for variables. Now, using encapsulation in modules, I guess it would look like this: import qualified LayoutItem (x, y) import LayoutItem ( LayoutItem ) import qualified Notehead (x, y) import Notehead ( Notehead ) foo :: LayoutItem -> Notehead -> Int foo l n = let y = LayoutItem.x l + Notehead.x n z = LayoutItem.y l + Notehead.y n in z + y From cowscanfly at airpost.net Thu Apr 2 19:18:29 2009 From: cowscanfly at airpost.net (TG) Date: Thu Apr 2 19:05:35 2009 Subject: [Haskell-beginners] What is "~" ? Message-ID: <1238714309.15888.1308710553@webmail.messagingengine.com> Looking at the definition of "partition", it calls select :: (a -> Bool) -> a -> ([a], [a]) -> ([a], [a]) select p x ~(ts,fs) | p x = (x:ts,fs) | otherwise = (ts, x:fs) what does the "~" do? Can't seem to find it in the documentation, or see a difference in output without it. Thank you. -- TG cowscanfly@airpost.net -- http://www.fastmail.fm - Email service worth paying for. Try it for free From rk at trie.org Thu Apr 2 19:21:04 2009 From: rk at trie.org (Rahul Kapoor) Date: Thu Apr 2 19:08:10 2009 Subject: [Haskell-beginners] What is "~" ? In-Reply-To: <1238714309.15888.1308710553@webmail.messagingengine.com> References: <1238714309.15888.1308710553@webmail.messagingengine.com> Message-ID: ~ signifies a lazy pattern. See: http://www.haskell.org/tutorial/patterns.html for more details. Rahul What kind of art do you like? http://www.artquiver.com On Thu, Apr 2, 2009 at 7:18 PM, TG wrote: > Looking at the definition of "partition", it calls > > ? ?select :: (a -> Bool) -> a -> ([a], [a]) -> ([a], [a]) > ? ?select p x ~(ts,fs) | p x ? ? ? = (x:ts,fs) > ? ? ? ? ? ? ? ? ? ? ? ?| otherwise = (ts, x:fs) > > what does the "~" do? > Can't seem to find it in the documentation, or see a difference in > output without it. > Thank you. > -- > ?TG > ?cowscanfly@airpost.net > > -- > http://www.fastmail.fm - Email service worth paying for. Try it for free > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > From apfelmus at quantentunnel.de Thu Apr 2 20:18:39 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Thu Apr 2 20:06:03 2009 Subject: [Haskell-beginners] Re: CORRECTED: making translation from imperative code] In-Reply-To: <49D50B08.4080707@alumni.caltech.edu> References: <49D50B08.4080707@alumni.caltech.edu> Message-ID: Michael Mossey wrote: > Read this version. > > A composition consists of several voices or instruments, each indicated > by its own *staff*. Visually, a staff is a layout of items such as > notes, clef signs, and accidentals arranged horizontally from left to > right, representing increasing time. > > > A *system* is a set of staves stacked vertically that represent > instruments playing at the same time. > > Here is a simple representation of a system, in which the pipe character > represents items. Note that some of the items are aligned vertically > meaning they will play at the same time. At other times, only one > staff contains a note. > > staff 1: | | | | > staff 2: | | | | > > Next we elaborate this model to show that items have visual width. Here > they are represented by clusters of x's with a pipe in the middle. The pipe > represents the part of the item that needs to be aligned with items on > other staves. For example, in the visual representation of a chord, > the part of the chord called the notehead needs to be aligned with > noteheads on other staves. (A chord includes other symbols, like > accidentals > and flags, which get drawn to the right or left of the notehead and don't > need to be aligned vertically with anything else.) > > > staff 1: x|x xx|xx x|x > > staff 2: x|x x|x xxxxx|xxxxx > > a b c d > > Here you can see that there is an additional constraint on layout, > which is that items need to have horizontal space around them so they > don't collide. For instance, the very wide item at 'd' (on staff 2) means > that the item on staff 1 at 'd' has to be positioned far to the right > of its previous item. A nice problem with an elegant solution. Let me demonstrate. First, let's solve the simpler problem of aligning just a single staff on unlimited paper. In other words, we are given a list of items that extend to the left and right, and we want to calculate a position for each one. In fact, let's dispense with items entirely and just work with a list of extents directly. type Pos = Integer type Width = Pos align :: [(Width,Width)] -> [Pos] For instance, the item (3,4) corresponds to xxx|xxxx Implementing this functions is straightforward align xs = scanl (+) a gaps where (a:as,bs) = unzip xs gaps = zipWith (+) bs as This is a very tight layout without any whitespace, but we can add some after the fact addWhitespace :: Width -> [Pos] -> [Pos] addWhitespace margin = zipWith (+) [0,margin..] With this, we can now align a list of events (from my previous message) given a function that tells us their visual extents. alignStaff :: (a -> (Width,Width)) -> Events a -> [Pos] alignStaff f = align . map f Now, what about the problem of aligning several staves on unlimited paper? It turns out that we've already solved it! After all, we can interpret a vertical group of items as a compound item whose total width is just the maximum width of its components. alignStaves :: (a -> (Width,Width)) -> [Events a] -> [Pos] alignStaves f = alignStaff f' . merge where f' = (maximum *** maximum) . unzip . map f In other words, we can lay out a group of staves by first merging them in time order (as done in my previous post) and then treating the result as a "compound" staff. > Note that data exists in two domains: there is data that describes notes; > that is, pitches and timbres and volumes and times and duration. We'll > call this the 'score'. It's the fundamental data. Then there is the > visual *representation* of the score. Here we are concerned only with > creating a visual representation. However, we need to refer to > data in the score. Thanks to polymorphism, keeping this data around is no problem. The alignStaves function simply doesn't care what items it is going to align, it only wants to know their widths. In fact, making alignStave polymorphic is key to reusing it for groups of staves. In other words, polymorphism is key to separating concerns. You should structure your layout engine as some kind of library that can align anything, caring only about widths and heights. For instance, dealing with finite paper size can be packed neatly into the align function. Regards, apfelmus -- http://apfelmus.nfshost.com From ivan.r.moore at gmail.com Thu Apr 2 05:46:29 2009 From: ivan.r.moore at gmail.com (Ivan Moore) Date: Thu Apr 2 22:28:12 2009 Subject: [Haskell-beginners] beginner's type error In-Reply-To: <42784f260903301809i786dd1d4u6a03f09364caa7f6@mail.gmail.com> References: <65e79fa10903261501v4dcbe888w3f0cbe10f9f2112a@mail.gmail.com> <20090327130710.GC23022@seas.upenn.edu> <65e79fa10903271244k184ff62dta82b62583be7440c@mail.gmail.com> <42784f260903301809i786dd1d4u6a03f09364caa7f6@mail.gmail.com> Message-ID: <65e79fa10904020246i41799da2g2e232e9d74cdd79@mail.gmail.com> without engaging my brain too much, given what you've said, then why is "10" both integral and floating point? why not "10" being integral and "10.0" being floating point? On Tue, Mar 31, 2009 at 2:09 AM, Jason Dusek wrote: > 2009/03/27 Ivan Moore : >> > The reason (which is a bit confusing) is that it typechecks >> > just fine---if there *were* a type which is an instance of >> > both Integral and Floating (and I guess round needs RealFrac >> > as well), n could have that type. There isn't such a type >> > in the standard libraries, but in theory you could make up >> > your own type which is an instance of both. >> >> If there were such a type, could "10" have that type and then >> would my problem have not existed? > > Yes, that is correct. > >> in which case, why doesn't it!? > > Does it actually make any logical sense for a type to be both > integral (governed by rules of modular division) and floating > point (governed by rules of IEEE 754 division)? > > -- > Jason Dusek > From haskell at colquitt.org Fri Apr 3 02:33:07 2009 From: haskell at colquitt.org (John Dorsey) Date: Fri Apr 3 02:20:12 2009 Subject: [Haskell-beginners] beginner's type error In-Reply-To: <65e79fa10904020246i41799da2g2e232e9d74cdd79@mail.gmail.com> References: <65e79fa10903261501v4dcbe888w3f0cbe10f9f2112a@mail.gmail.com> <20090327130710.GC23022@seas.upenn.edu> <65e79fa10903271244k184ff62dta82b62583be7440c@mail.gmail.com> <42784f260903301809i786dd1d4u6a03f09364caa7f6@mail.gmail.com> <65e79fa10904020246i41799da2g2e232e9d74cdd79@mail.gmail.com> Message-ID: <20090403063307.GA2207@colquitt.org> Ivan, > without engaging my brain too much, given what you've said, then why > is "10" both integral and floating point? why not "10" being integral > and "10.0" being floating point? The literal "10", as it appears in Haskell source, stands for something that can take on any numeric type, but as soon as you use it in a context that constrains it, well, it gets constrained! "10" can be integral, or it can be floating point. As I think Jason was saying, *if* there was a type that was both integral and floating point, then 10 could represent something of that type. But there's no *sensible* type that has both integral and floating point nature. (At least none that comes to mind. Maybe you could do something with symbolic manipulation that would make sense.) Leaving behind sensible types, we can define one that's both integral and fractional. I'm going to violate all kinds of commonly assumed (but unenforced) laws of the numeric classes, in an act of self-loathing, so enjoy the following abomination! The code is appended at the end of this message. dorsey@elwood:~/src/scratch$ ghci int-float.hs *Main> :t munge munge :: IntFloat -> IntFloat *Main> :t munge 10 munge 10 :: IntFloat *Main> fromIntegral (munge 10) 42 If you look at the code for munge below, you'll see that I've mixed integral operations (div) with floating point operations (**) and fractional operations (/). I have no trouble applying munge to 10. The literal "10" (which really means "fromIntegral 10") takes on the right type because it has to to match munge's argument type. So why would I choose to do this terrible thing? To illustrate that: 1) The open world assumption of Haskell type classes implies that a type like this could be definied later, even if it doesn't exist now. 2) Even though you can do this and obey the type rules, I had to use a silly type, with very silly class instance definitions. Integral things just aren't fractional! To answer you other specific question, about why they didn't just distinguish "10" from "10.0" as some other languages do, the original motivation was well before my time. But it does seem to me that being able to use "10" to refer not only to Integers and Floats, but also to Ints, Int16s, Doubles, and many unforseen numeric types, was a clever choice. Sadly, numeric literals make the short-list of things that confuse Haskell neophites the most. I hope all this is at least either interesting or helpful. Regards, John -- int-float.hs -- a datatype inhabiting floating and integral classes, -- but which doesn't model numerics particularly well data IntFloat = IF String deriving (Show, Eq, Ord) munge :: IntFloat -> IntFloat munge x = x / x `div` x ** x instance Num IntFloat where _ + _ = IF "sum" _ - _ = IF "difference" _ * _ = IF "product" negate _ = IF "negation" abs _ = IF "abs" signum _ = IF "signum" fromInteger _ = IF "fromInteger" instance Integral IntFloat where quot _ _ = IF "quot" rem _ _ = IF "rem" div _ _ = IF "div" mod _ _ = IF "mod" quotRem _ _ = (IF "quotRem quot", IF "quotRem rem") divMod _ _ = (IF "divMod div", IF "divMod mod") toInteger _ = 42 instance Floating IntFloat where pi = IF "pi" exp _ = IF "exp" sqrt _ = IF "sqrt" log _ = IF "log" (**) _ _ = IF "**" logBase _ _ = IF "logBase" sin _ = IF "sin" tan _ = IF "tan" cos _ = IF "cos" asin _ = IF "asin" atan _ = IF "atan" acos _ = IF "acos" sinh _ = IF "sinh" tanh _ = IF "tanh" cosh _ = IF "cosh" asinh _ = IF "asinh" atanh _ = IF "atanh" acosh _ = IF "acosh" instance Real IntFloat where toRational _ = toRational 42 instance Enum IntFloat where succ _ = IF "succ" pred _ = IF "pred" toEnum _ = IF "toEnum" fromEnum _ = 42 enumFrom _ = [IF "enumFrom"] enumFromThen _ _ = [IF "enumFromThen"] enumFromTo _ _ = [IF "enumFromTo"] enumFromThenTo _ _ _ = [IF "enumFromThenTo"] instance Fractional IntFloat where (/) _ _ = IF "/" recip _ = IF "recip" fromRational _ = IF "fromRational" From divisortheory at gmail.com Fri Apr 3 21:58:41 2009 From: divisortheory at gmail.com (Zachary Turner) Date: Fri Apr 3 21:45:43 2009 Subject: [Haskell-beginners] Is this overkill? Message-ID: <478231340904031858t7bc3a7c7i67096058a9b21fb2@mail.gmail.com> I thought I would try to see if it were possible to write, in point-free form using no lambda functions and no intermediate functions, a function that takes 2 lists of Booleans, computes the pairwise logical AND of the two lists, and returns a list containing the 0 based indices of the elements where the logical and of the two was true. I know that at some point it becomes overkill and for the sake of readability one should know when to draw the line. So I want to see if someone with more experience than me can comment on whether or not this is over the line :P trueIndices = curry $ map fst . filter snd . zip [0..] . map (uncurry (&&)) . (uncurry zip) So do all the uncurries and curries make it too hard to understand or is it pretty easy to read this? For me it takes me a while to figure out by looking at it because it's hard to trace all the currying and uncurrying. And is there a more elegant solution? -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090403/4a7bc302/attachment.htm From felipe.lessa at gmail.com Fri Apr 3 22:16:30 2009 From: felipe.lessa at gmail.com (Felipe Lessa) Date: Fri Apr 3 22:03:37 2009 Subject: [Haskell-beginners] Is this overkill? In-Reply-To: <478231340904031858t7bc3a7c7i67096058a9b21fb2@mail.gmail.com> References: <478231340904031858t7bc3a7c7i67096058a9b21fb2@mail.gmail.com> Message-ID: <20090404021630.GA25199@kira.casa> On Fri, Apr 03, 2009 at 08:58:41PM -0500, Zachary Turner wrote: > trueIndices = curry $ map fst . filter snd . zip [0..] . map (uncurry (&&)) > . (uncurry zip) Just some tips: note that map (uncurry f) . zip === zipWith f curry $ f . uncurry g === (f .) . g so trueIndices = ((map fst . filter snd . zip [0..]) .) . zipWith (&&) There must be some combinators to avoid the '((...) .) .' thing, though. I just don't remember :). HTH, -- Felipe. From apfelmus at quantentunnel.de Fri Apr 3 22:30:12 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Fri Apr 3 22:17:32 2009 Subject: [Haskell-beginners] Re: Is this overkill? In-Reply-To: <478231340904031858t7bc3a7c7i67096058a9b21fb2@mail.gmail.com> References: <478231340904031858t7bc3a7c7i67096058a9b21fb2@mail.gmail.com> Message-ID: Zachary Turner wrote: > I thought I would try to see if it were possible to write, in point-free > form using no lambda functions and no intermediate functions, a function > that takes 2 lists of Booleans, computes the pairwise logical AND of the two > lists, and returns a list containing the 0 based indices of the elements > where the logical and of the two was true. I know that at some point it > becomes overkill and for the sake of readability one should know when to > draw the line. So I want to see if someone with more experience than me can > comment on whether or not this is over the line :P > > trueIndices = curry $ map fst . filter snd . zip [0..] . map (uncurry (&&)) > .. (uncurry zip) > > So do all the uncurries and curries make it too hard to understand or is it > pretty easy to read this? For me it takes me a while to figure out by > looking at it because it's hard to trace all the currying and uncurrying. > And is there a more elegant solution? Looks very readable to me, though I'd write it as trueIndices = (map fst . filter snd . zip [0..] .) . zipWith (&&) or even simply as trueIndices xs ys = map fst . filter snd . zip [0..] $ zipWith (&&) xs ys because composing functions with more than one argument tends to be a bit messy. With Conal's semantic editor combinators http://conal.net/blog/posts/semantic-editor-combinators/ it would be written as trueIndices = (result . result) (map fst . filter snd . zip [0..]) (zipWith (&&)) Regards, apfelmus -- http://apfelmus.nfshost.com From divisortheory at gmail.com Fri Apr 3 23:20:10 2009 From: divisortheory at gmail.com (Zachary Turner) Date: Fri Apr 3 23:07:11 2009 Subject: [Haskell-beginners] Re: Is this overkill? In-Reply-To: References: <478231340904031858t7bc3a7c7i67096058a9b21fb2@mail.gmail.com> Message-ID: <478231340904032020v4ad1b2e9jb4f6bc64bd77b66@mail.gmail.com> On Fri, Apr 3, 2009 at 9:30 PM, Heinrich Apfelmus wrote: > Zachary Turner wrote: > > I thought I would try to see if it were possible to write, in point-free > > form using no lambda functions and no intermediate functions, a function > > that takes 2 lists of Booleans, computes the pairwise logical AND of the > two > > lists, and returns a list containing the 0 based indices of the elements > > where the logical and of the two was true. I know that at some point it > > becomes overkill and for the sake of readability one should know when to > > draw the line. So I want to see if someone with more experience than me > can > > comment on whether or not this is over the line :P > > > > trueIndices = curry $ map fst . filter snd . zip [0..] . map (uncurry > (&&)) > > .. (uncurry zip) > > > > So do all the uncurries and curries make it too hard to understand or is > it > > pretty easy to read this? For me it takes me a while to figure out by > > looking at it because it's hard to trace all the currying and uncurrying. > > And is there a more elegant solution? > > Looks very readable to me, though I'd write it as > > trueIndices = (map fst . filter snd . zip [0..] .) . zipWith (&&) > > or even simply as > > trueIndices xs ys = > map fst . filter snd . zip [0..] $ zipWith (&&) xs ys > > because composing functions with more than one argument tends to be a > bit messy. > > > With Conal's semantic editor combinators > > http://conal.net/blog/posts/semantic-editor-combinators/ > > it would be written as > > trueIndices = > (result . result) (map fst . filter snd . zip [0..]) (zipWith (&&)) > That was a pretty interesting blog post, and easily understandable which is always nice. Thanks for the link. I also had never even used the zipWith function, so thanks for pointing out that equivalence. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090403/691113d2/attachment.htm From mpm at alumni.caltech.edu Sat Apr 4 05:09:26 2009 From: mpm at alumni.caltech.edu (Michael Mossey) Date: Sat Apr 4 04:56:34 2009 Subject: [Haskell-beginners] Re: CORRECTED: making translation from imperative code] In-Reply-To: References: <49D50B08.4080707@alumni.caltech.edu> Message-ID: <49D723C6.4070905@alumni.caltech.edu> Heinrich Apfelmus wrote: > Michael Mossey wrote: >> Read this version. >> >> A composition consists of several voices or instruments, each indicated >> by its own *staff*. Visually, a staff is a layout of items such as >> notes, clef signs, and accidentals arranged horizontally from left to >> right, representing increasing time. >> >> >> A *system* is a set of staves stacked vertically that represent >> instruments playing at the same time. >> >> Here is a simple representation of a system, in which the pipe character >> represents items. Note that some of the items are aligned vertically >> meaning they will play at the same time. At other times, only one >> staff contains a note. >> >> staff 1: | | | | >> staff 2: | | | | >> >> Next we elaborate this model to show that items have visual width. Here >> they are represented by clusters of x's with a pipe in the middle. The pipe >> represents the part of the item that needs to be aligned with items on >> other staves. For example, in the visual representation of a chord, >> the part of the chord called the notehead needs to be aligned with >> noteheads on other staves. (A chord includes other symbols, like >> accidentals >> and flags, which get drawn to the right or left of the notehead and don't >> need to be aligned vertically with anything else.) >> >> >> staff 1: x|x xx|xx x|x >> >> staff 2: x|x x|x xxxxx|xxxxx >> >> a b c d >> >> Here you can see that there is an additional constraint on layout, >> which is that items need to have horizontal space around them so they >> don't collide. For instance, the very wide item at 'd' (on staff 2) means >> that the item on staff 1 at 'd' has to be positioned far to the right >> of its previous item. Hi Heinrich, Okay, I read all of your email, and there is one problem. My layout problem is more complex than I communicated at first. Let me give a more detailed example: staff 1: xxxx|xxxx x|x staff 2: x|xx xxxx|xx staff 3: x|x a b c There are two additional concerns to what you coded up. Notice that parts of events on different staves are allowed to overlap. To determine the spacing from a to b, one has to know the widths of items on each staff to see that they they can be placed with some overlap but won't collide. They can't be treated strictly as a compound item and "going blind" to the parts that make them up. Secondly, look at the item on staff 3 at c. It has no prior item to avoid colliding with, and no items on other staves to line up with, but there is still a constraint on its position: c > b (by some amount that can be experimented with). Here is something I coded up, but didn't test much (other than it compiles): -- Item is a pair giving left width and right width. -- Chunk represents items that must align. There may not be one on every staff, -- hence the use of Maybe type Item = (Int, Int) type Chunk = [ Maybe Item ] -- layout3, given a list of Chunks, will produce a list of integer positions where -- they should be placed. layout3 :: [ Chunk ] -> [ Int ] layout3 cs = layout3' cs (replicate (length cs) 0) -- helper function layout3' takes list of chunks, integer list of "right extents" -- (how far to the right each staff extends at that time), and minimum position -- (which is, in this case, always 1 greater than prior placement position) layout3' :: [ Chunk ] -> [ Int ] -> Int -> [ Int ] layout3' [] _ _ = [] layout3' (c:cs) rs minP = p : layout3' cs rs' (p + 1) where p = maximum $ minP : (map place (zip c rs)) rs' = map advance (zip c rs) place (item, r) = case item of Just ( left, right ) -> r + left _ -> 0 advance (item, p ) = case item of Just ( left, right ) -> p + right _ -> p The near identical functions place and advance really need to be merged. Thanks, Mike From aleks.dimitrov at googlemail.com Sat Apr 4 10:39:51 2009 From: aleks.dimitrov at googlemail.com (=?utf-8?B?0JDQu9C10LrRgdCw0L3QtNGK0YAg0JsuINCU0LjQvNC40YLRgNC+0LI=?=) Date: Sat Apr 4 10:01:54 2009 Subject: [Haskell-beginners] Event handling in GTK2hs: managing events and global state In-Reply-To: <82A1B66A-ED3E-4AB4-9E51-F3419D87CCFB@ece.cmu.edu> References: <20090325042430.GA4707@brmbr.sfs.uni-tuebingen.de> <82A1B66A-ED3E-4AB4-9E51-F3419D87CCFB@ece.cmu.edu> Message-ID: <20090404143951.GA29578@kumar.sfs.uni-tuebingen.de> Also Sprach Brandon S. Allbery KF8NH: > You can make it "global" without using unsafePerformIO: Set up a > ReaderT MyState IO and run the program inside it, after initializing > your MyState with appropriate IORefs. You need to lift gtk2hs > functions, and callbacks have to be wrapped to push them back up into > the ReaderT: > > curState <- ask > lift $ widget `on` buttonPressEvent $ runReaderT curState . > myCallback > > The reason you want a ReaderT instead of a StateT is that any state not > accessed via an IORef can't be propagated between the mainline code and > callbacks, so you want something that is forced to be read-only after > initialization except via an IORef stored within it. > > Aside: I've suggested at times that gtk2hs use class MonadIO instead of > type IO, which would make explicit lifting (and I think "dropping") > unnecessary. I never made a formal enhancement suggestion though; I > should do so. Thanks for your very helpful answer :-) I ended up passing a state object around in functions and then porting it back to use the Monad (damn deadlines, always in the way of sound programming.) If the GTK2hs people made this a bit easier, it would surely help. I'll look into the possibilities myself, too. Thanks again, Aleks -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 197 bytes Desc: not available Url : http://www.haskell.org/pipermail/beginners/attachments/20090404/0352cd1b/attachment.bin From aleks.dimitrov at googlemail.com Sat Apr 4 11:06:10 2009 From: aleks.dimitrov at googlemail.com (=?utf-8?B?0JDQu9C10LrRgdCw0L3QtNGK0YAg0JsuINCU0LjQvNC40YLRgNC+0LI=?=) Date: Sat Apr 4 10:28:07 2009 Subject: [Haskell-beginners] Differences between OO-style Interfaces and type classes. Any 'Haskell' way of doing it? Message-ID: <20090404150610.GB29578@kumar.sfs.uni-tuebingen.de> Hello folks, thanks for being such a very nice and helpful community :-) I have another pretty boring question? Today I noticed where type classes and OO-Interfaces differ. Up until now, I treated the two notions as pretty much equivalent, but knowing that there are some differences I do not yet understand. Now I do understand at least one of them. Say I have several types Type, Subtype, Subsubtype and so on. All are instances of a type class Class. The constructors all look like > data Type = Type (Maybe Subtype) > data Subtype = Subtype (Maybe Subsubtype) and so on. I would now like to build a tree structure with Data.Tree which only holds the type constructors as partial functions and be able to fold over the tree to yield a complete value of type Type. So a user could select any point of the tree (whether leaf or not) and she would get this node's type combined with all the parent's node's types. A small example: 0,Type | `- 1,A | `- 3,C `- 2,B Selecting node 1 would result in the type (Type (Just (A Nothing))) returned and selecting node 0 would return (Type Nothing). Assuming all types implement Class, I thought equipping the nodes of a Data.Tree with a type like (Class a) => Node (Maybe a -> a) would work. Of course it didn't, because it couldn't unify the Subtype with the Type. The reason I need this is because I have a HaXml generated file with data types from a DTD, and would like to display them in a GTK TreeModel so the user could choose a type there and have it turned to XML. The class of all DTD-originated types is, of course, XmlContent. So, my problem here is: I'd like a tree to store partial functions of possibly different types and then be able to compose a leaf's or non-leaf's payload with all the parent's payloads to yield a final result. Writing up my idea made me realise how ludicrous it is from a theoretical point of view, and that Data.Tree might simply not be the correct data structure for this (alas, it's required for TreeModels in GTK.) At least it can serve as an example to people where type classes do not act like Interfaces ;-) And I'd be very glad to hear about a solution to my problem, it would make some things a lot easier for me :-). Thanks again, Aleks -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 197 bytes Desc: not available Url : http://www.haskell.org/pipermail/beginners/attachments/20090404/d1b94ce8/attachment.bin From allbery at ece.cmu.edu Sat Apr 4 13:08:23 2009 From: allbery at ece.cmu.edu (Brandon S. Allbery KF8NH) Date: Sat Apr 4 12:55:36 2009 Subject: [Haskell-beginners] Differences between OO-style Interfaces and type classes. Any 'Haskell' way of doing it? In-Reply-To: <20090404150610.GB29578@kumar.sfs.uni-tuebingen.de> References: <20090404150610.GB29578@kumar.sfs.uni-tuebingen.de> Message-ID: <11ECA348-D3D2-4CFF-9A0A-01BE82D4DA02@ece.cmu.edu> On 2009 Apr 4, at 11:06, ?????????? ?. ???????? wrote: > So, my problem here is: I'd like a tree to store partial functions > of possibly > different types and then be able to compose a leaf's or non-leaf's > payload with > all the parent's payloads to yield a final result. Have you considered using generics? -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH -------------- next part -------------- A non-text attachment was scrubbed... Name: PGP.sig Type: application/pgp-signature Size: 195 bytes Desc: This is a digitally signed message part Url : http://www.haskell.org/pipermail/beginners/attachments/20090404/398039c2/PGP.bin From chaddai.fouche at gmail.com Sun Apr 5 11:57:13 2009 From: chaddai.fouche at gmail.com (=?UTF-8?B?Q2hhZGRhw68gRm91Y2jDqQ==?=) Date: Sun Apr 5 11:44:15 2009 Subject: [Haskell-beginners] Re: Is this overkill? In-Reply-To: <478231340904032020v4ad1b2e9jb4f6bc64bd77b66@mail.gmail.com> References: <478231340904031858t7bc3a7c7i67096058a9b21fb2@mail.gmail.com> <478231340904032020v4ad1b2e9jb4f6bc64bd77b66@mail.gmail.com> Message-ID: On Sat, Apr 4, 2009 at 5:20 AM, Zachary Turner wrote: >> With Conal's semantic editor combinators >> >> ?http://conal.net/blog/posts/semantic-editor-combinators/ >> >> it would be written as >> >> ?trueIndices = >> ? ?(result . result) (map fst . filter snd . zip [0..]) (zipWith (&&)) > > > That was a pretty interesting blog post, and easily understandable which is > always nice.? Thanks for the link.? I also had never even used the zipWith > function, so thanks for pointing out that equivalence. I'm not sure you really want to write this pointfree... Generally I tend to avoid it when there's two arguments of identical standing. Also the (map fst . filter snd...) is a Data.List function (findIndices) : trueIndices xs ys = findindices id $ zipWith (&&) xs ys I love the pointfree style and it might be a good exercise to try and transcribe any function to pointfree, but sometimes pointful is just clearer. -- Jeda? From magnus at therning.org Sun Apr 5 12:08:20 2009 From: magnus at therning.org (Magnus Therning) Date: Sun Apr 5 11:55:20 2009 Subject: [Haskell-beginners] Re: Is this overkill? In-Reply-To: References: <478231340904031858t7bc3a7c7i67096058a9b21fb2@mail.gmail.com> <478231340904032020v4ad1b2e9jb4f6bc64bd77b66@mail.gmail.com> Message-ID: <49D8D774.9030106@therning.org> Chadda? Fouch? wrote: > On Sat, Apr 4, 2009 at 5:20 AM, Zachary Turner wrote: >>> With Conal's semantic editor combinators >>> >>> http://conal.net/blog/posts/semantic-editor-combinators/ >>> >>> it would be written as >>> >>> trueIndices = >>> (result . result) (map fst . filter snd . zip [0..]) (zipWith (&&)) >> >> That was a pretty interesting blog post, and easily understandable which is >> always nice. Thanks for the link. I also had never even used the zipWith >> function, so thanks for pointing out that equivalence. > > I'm not sure you really want to write this pointfree... Generally I > tend to avoid it when there's two arguments of identical standing. > Also the (map fst . filter snd...) is a Data.List function > (findIndices) : > > trueIndices xs ys = findindices id $ zipWith (&&) xs ys > > I love the pointfree style and it might be a good exercise to try and > transcribe any function to pointfree, but sometimes pointful is just > clearer. Or to put it differently, sometimes "pointfree is pointless" ;-) /M -- Magnus Therning (OpenPGP: 0xAB4DFBA4) magnus?therning?org Jabber: magnus?therning?org http://therning.org/magnus identi.ca|twitter: magthe Haskell is an even 'redder' pill than Lisp or Scheme. -- PaulPotts -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 197 bytes Desc: OpenPGP digital signature Url : http://www.haskell.org/pipermail/beginners/attachments/20090405/cdb91aa1/signature.bin From adamkkeys at gmail.com Sun Apr 5 23:07:16 2009 From: adamkkeys at gmail.com (Adam Keys) Date: Sun Apr 5 22:54:15 2009 Subject: [Haskell-beginners] Fetching a URI Message-ID: I'm trying to write a wrapper for a REST service. However, I find myself stumped by the simplest part: merely performing a GET on a URI. I'm using the HTTP Cabal package. It specifies an example like so: > simpleHTTP (getRequest "http://www.haskell.org/") >>= fmap (take > 100) . getResponseBody However, it seems I'm either importing the library incorrectly or there is a discrepancy between the documentation and the library. I can't seem to call getRequest. > :) ghc-pkg list > ... > /Users/adamkeys/.ghc/i386-darwin-6.8.2/package.conf: > Cabal-1.6.0.1, HTTP-3001.1.3, HTTP-4000.0.4, Shellac-0.9.5, > ... > > GHCi, version 6.8.2: http://www.haskell.org/ghc/ :? for help > Loading package base ... linking ... done. > Prelude> import Network.HTTP > Prelude Network.HTTP> :type getRequest > > :1:0: Not in scope: `getRequest' Am I missing something obvious here? -- ~akk From aditya.siram at gmail.com Sun Apr 5 23:46:04 2009 From: aditya.siram at gmail.com (aditya siram) Date: Sun Apr 5 23:32:59 2009 Subject: [Haskell-beginners] Fetching a URI In-Reply-To: References: Message-ID: <594f78210904052046w117a08fbq4ed498fa43300087@mail.gmail.com> At first I got the same error but when I installed HTTP-4000.0.5 using Cabal your code worked. hth, deech On Sun, Apr 5, 2009 at 10:07 PM, Adam Keys wrote: > I'm trying to write a wrapper for a REST service. However, I find myself > stumped by the simplest part: merely performing a GET on a URI. > > I'm using the HTTP Cabal package. It specifies an example like so: > > simpleHTTP (getRequest "http://www.haskell.org/") >>= fmap (take 100) . >> getResponseBody >> > > > However, it seems I'm either importing the library incorrectly or there is > a discrepancy between the documentation and the library. I can't seem to > call getRequest. > > :) ghc-pkg list >> ... >> /Users/adamkeys/.ghc/i386-darwin-6.8.2/package.conf: >> Cabal-1.6.0.1, HTTP-3001.1.3, HTTP-4000.0.4, Shellac-0.9.5, >> ... >> >> GHCi, version 6.8.2: http://www.haskell.org/ghc/ :? for help >> Loading package base ... linking ... done. >> Prelude> import Network.HTTP >> Prelude Network.HTTP> :type getRequest >> >> :1:0: Not in scope: `getRequest' >> > > Am I missing something obvious here? > > -- > ~akk > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090405/be4f76a1/attachment.htm From aleks.dimitrov at googlemail.com Mon Apr 6 08:37:47 2009 From: aleks.dimitrov at googlemail.com (Aleksandar Dimitrov) Date: Mon Apr 6 08:24:56 2009 Subject: [Haskell-beginners] Fetching a URI In-Reply-To: References: Message-ID: Hi Adam, >> ghc-pkg list >> ... >> /Users/adamkeys/.ghc/i386-darwin-6.8.2/package.conf: >> Cabal-1.6.0.1, HTTP-3001.1.3, HTTP-4000.0.4, Shellac-0.9.5, >> ... It seems you have two versions of HTTP installed. I'm not really sure about HTTP-3.x.x.x's API, but I'd wage a guess that it doesn't define `getRequest`. When importing in ghci, your installation probably picks the older one instead of the new version. Try hiding the old package and see if it fixes your problem: > ghc-pkg hide HTTP-3001.1.13 You can unhide it using `ghc-pkg unhide HTTP-3001.1.13`. HTH, Aleks From mpm at alumni.caltech.edu Tue Apr 7 03:01:12 2009 From: mpm at alumni.caltech.edu (Michael Mossey) Date: Tue Apr 7 02:48:15 2009 Subject: [Haskell-beginners] accessor function scope Message-ID: <49DAFA38.4020906@alumni.caltech.edu> I'm coming from the OO world and trying to adapt. I've noticed that if I declare two types like this data Thing1 = Thing1 { itemPos :: Int } data Thing2 = Thing2 { itemPos :: Int } then I get the error "Multiple declarations of Main.itemPos" However, I can successfully do this: type Pos = ( Int, Int ) type Dimension = ( Int, Int, Int, Int ) data LayoutItem = StaffItem { itemPos :: Pos, itemDim :: Dimension } | TextItem { itemPos :: Pos, itemDim :: Dimension } d1 = TextItem ... d2 = StaffItem ... i1 = itemPos d i2 = itemPos d2 This seems to define itemPos in a way that can sense whether it's dealing with a StaffItem-type LayoutItem or a TextItem-type LayoutItem. I don't know if this would be considered an overloaded operator. However, it does resemble derived class in OO. For that matter, I don't know what the term is for a "StaffItem-type LayoutItem". The type is clearly LayoutItem. "StaffItem" is the constructor. How do you refer to the concept of a LayoutItem constructed via a StaffItem? Again, StaffItem and TextItem resemble derived classes in OO. Any clarification welcome. -Mike From mpm at alumni.caltech.edu Tue Apr 7 03:30:04 2009 From: mpm at alumni.caltech.edu (Michael Mossey) Date: Tue Apr 7 03:17:11 2009 Subject: [Haskell-beginners] combine pattern matching against named fields and tuples Message-ID: <49DB00FC.5050904@alumni.caltech.edu> I'm trying to do something like this: data Thing = Thing { field1, field2 :: ( Int, Int ) } myfunc = Thing { field1 ( _, x ) } = x but it doesn't work. That is, I want to match against the second item of the tuple which is the named field1. I'm not just trying to do this particular thing, but trying to figure out if some kind of general pattern matching can be done like this. From allbery at ece.cmu.edu Tue Apr 7 03:37:02 2009 From: allbery at ece.cmu.edu (Brandon S. Allbery KF8NH) Date: Tue Apr 7 03:24:20 2009 Subject: [Haskell-beginners] combine pattern matching against named fields and tuples In-Reply-To: <49DB00FC.5050904@alumni.caltech.edu> References: <49DB00FC.5050904@alumni.caltech.edu> Message-ID: On 2009 Apr 7, at 3:30, Michael Mossey wrote: > I'm trying to do something like this: > > data Thing = Thing { field1, field2 :: ( Int, Int ) } > > myfunc = Thing { field1 ( _, x ) } = x > myfunc (Thing {field1 = (_,x)}) = x using record pattern matching -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH -------------- next part -------------- A non-text attachment was scrubbed... Name: PGP.sig Type: application/pgp-signature Size: 195 bytes Desc: This is a digitally signed message part Url : http://www.haskell.org/pipermail/beginners/attachments/20090407/3bf147a7/PGP.bin From tom.davie at gmail.com Tue Apr 7 03:40:02 2009 From: tom.davie at gmail.com (Thomas Davie) Date: Tue Apr 7 03:27:12 2009 Subject: [Haskell-beginners] combine pattern matching against named fields and tuples In-Reply-To: <49DB00FC.5050904@alumni.caltech.edu> References: <49DB00FC.5050904@alumni.caltech.edu> Message-ID: <8FBB5FBD-456B-4A6C-81FD-E5D8A2D80BB0@gmail.com> On 7 Apr 2009, at 09:30, Michael Mossey wrote: > I'm trying to do something like this: > > data Thing = Thing { field1, field2 :: ( Int, Int ) } > > myfunc = Thing { field1 ( _, x ) } = x > > but it doesn't work. That is, I want to match against the second > item of the tuple which is the named field1. I'm not just trying to > do this particular thing, but trying to figure out if some kind of > general pattern matching can be done like this. Firstly, you have an extra equals in there, secondly, in a pattern match constructions must go in parentheses, and finally, you're missing an equals inside the record: myFunc (Think {field1 = (_,x)}) = x Bob From bieffe62 at gmail.com Tue Apr 7 04:03:50 2009 From: bieffe62 at gmail.com (Francesco Bochicchio) Date: Tue Apr 7 03:50:42 2009 Subject: [Haskell-beginners] accessor function scope In-Reply-To: <49DAFA38.4020906@alumni.caltech.edu> References: <49DAFA38.4020906@alumni.caltech.edu> Message-ID: 2009/4/7 Michael Mossey > I'm coming from the OO world and trying to adapt. > me too :-) > > For that matter, I don't know what the term is for a "StaffItem-type > LayoutItem". The type is clearly LayoutItem. "StaffItem" is the constructor. > How do you refer to the concept of a LayoutItem constructed via a StaffItem? > > Again, StaffItem and TextItem resemble derived classes in OO. > To me, they are more close to C union : a data type than can alternatively have different structures, In your example, LayoutItem is a type name, while StaffItem and TextItem are constructor, that is functions. Saying that a function specializes a type is a bit of a stretch, I think ... Nevertheless, they can sometime be used to accomplish the same goal : where in OO you define an abstact class and then specialize with concrete classes to model a classification, in haskell you can define a data type with alternate constructors. I think that data types with alternate constructores are called algebraic data types in haskellese, but I'm not sure of that ... > > Any clarification welcome. > -Mike > Ciao ----- FB -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090407/2bfbb60a/attachment-0001.htm From mpm at alumni.caltech.edu Tue Apr 7 05:47:32 2009 From: mpm at alumni.caltech.edu (Michael Mossey) Date: Tue Apr 7 05:34:43 2009 Subject: [Haskell-beginners] accessor function scope In-Reply-To: References: <49DAFA38.4020906@alumni.caltech.edu> Message-ID: <49DB2134.7060002@alumni.caltech.edu> Francesco Bochicchio wrote: > > > me too :-) > > > Again, StaffItem and TextItem resemble derived classes in OO. > > > To me, they are more close to C union : a data type than can > alternatively have different structures, > In your example, LayoutItem is a type name, while StaffItem and TextItem > are constructor, that is functions. > Saying that a function specializes a type is a bit of a stretch, I think ... > > Nevertheless, they can sometime be used to accomplish the same goal : > where in OO you define an abstact class and then > specialize with concrete classes to model a classification, in haskell > you can define a data type with alternate constructors. > > I think that data types with alternate constructores are called > algebraic data types in haskellese, but I'm not sure of that ... Here's what I've learned from my investigations, but I welcome any clarifications. There are a few ways they don't resemble constructors in OO, or unions in C. They are "constructors", but also "take apart" the item in pattern matching. myfunc (StaffItem pos dimension) = ... myfunc (TextItem pos dimension) = ... You can also hide the constructors when you export a module. I could export LayoutItem but not StaffItem and TextItem, meaning that other code would see LayoutItem as a kind of abstract base class. When you name a field in each constructor (the same name), you can access that field on any LayoutItem without knowing its constructor using the accessor function for that field. This looks a lot like an abstract base class. data LayoutItem = TextItem { myField :: Int } | StaffItem { myField :: Int } x1 = TextItem { myField = 3 } x2 = STaffItem { myField = 4 } y1 = myField x1 y2 = myField x2 When I tried to make TextItem and StaffItem instances of a class, I got an error. They aren't really types. Only LayoutItem is the type. instance Eq TextItem where ... ---> ERROR! instance Eq StaffItem where ... ---> ERROR! instance Eq LayoutItem where... ---> ok Right now I'm just confused by how to translate an exising OO design. I'm porting a partially complete Python program to Haskell. There are many options. For instance I could set up a class called LayoutClass, make TextItem and StaffItem their own classes and make them instances of the class. -- Note: Now I can no longer have any overlapping field names data TextItem = TextItem { tField1, tField2 :: Int } data StaffItem = StaffItem { sField1, sField3 :: Int } class LayoutClass a where access1 :: a -> Int instance LayoutClass TextItem where access1 (TextItem t) = tField1 t instance LayoutClass StaffItem where access1 (StaffItem s ) = sField1 s Or put everything in its own module and use qualified names. Probably the best choice for future considerations. From haskell at colquitt.org Tue Apr 7 09:00:54 2009 From: haskell at colquitt.org (John Dorsey) Date: Tue Apr 7 08:47:47 2009 Subject: [Haskell-beginners] accessor function scope In-Reply-To: <49DAFA38.4020906@alumni.caltech.edu> References: <49DAFA38.4020906@alumni.caltech.edu> Message-ID: <20090407130054.GD2207@colquitt.org> > I've noticed that if I declare two types like this > > data Thing1 = Thing1 { itemPos :: Int } > data Thing2 = Thing2 { itemPos :: Int } > > then I get the error "Multiple declarations of Main.itemPos" Here's something to consider. What's the type of itemPos? In the above code, it can't be itemPos :: Thing1 -> Int because you want to be able to apply it to a Thing2. I suppose the compiler could, behind the scenes, create a typeclass like this: class ItemPosAble a where itemPos :: a -> Int instance ItemPosAble Thing1 where itemPos (Thing1 x) = x instance ItemPosAble Thing2 where itemPos (Thing2 x) = x Then itemPos has type itemPos :: (ItemPosAble t) => t -> Int Maybe that would work, modulo my typos. But it's messy, and it gets messier if itemPos doesn't have the same return type in all examples. It probably makes it harder to produce clear error messages when something goes wrong. There are probably other issues I haven't seen yet. At any rate, just disallowing this kind of "overloading" of the accessor function is simple, and works. As you point out later, you can reuse the name by separating namespaces using modules. > data LayoutItem = StaffItem { itemPos :: Pos, > itemDim :: Dimension } > | TextItem { itemPos :: Pos, > itemDim :: Dimension } Here the type of itemPos is clearly just itemPos :: LayoutItem -> Pos No problem. Behind the scenes, the compiler is defining it as something like itemPos (StaffItem x _) = x itemPos (TextItem x _) = x > This seems to define itemPos in a way that can sense whether it's dealing > with a StaffItem-type LayoutItem or a TextItem-type LayoutItem. I don't You're right that there's enough information to figure it out in this example code, but the type inference in Haskell doesn't do this kind of ad-hockery. > know if this would be considered an overloaded operator. However, it does > resemble derived class in OO. It's not a bad exercise to compare Haskell to what you already know, but expect it to break down before long. Clear and idiomatic functional design will generally look pretty different from clear and idiomatic OO design. That said, you can do OO stuff in Haskell; it's just not very fun, and generally not needed. > For that matter, I don't know what the term is for a "StaffItem-type > LayoutItem". The type is clearly LayoutItem. "StaffItem" is the > constructor. How do you refer to the concept of a LayoutItem constructed > via a StaffItem? You can just call it "a StaffItem", I guess. I don't know if there's a common term. But you're right that it's type is LayoutItem. Regards, John From daniel.is.fischer at web.de Tue Apr 7 09:15:00 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Tue Apr 7 09:02:32 2009 Subject: [Haskell-beginners] accessor function scope Message-ID: <200904071515.00936.daniel.is.fischer@web.de> Am Dienstag 07 April 2009 11:47:32 schrieb Michael Mossey: > Francesco Bochicchio wrote: > > me too :-) > > > > > > Again, StaffItem and TextItem resemble derived classes in OO. > > > > > > To me, they are more close to C union : a data type than can > > alternatively have different structures, Both analogies capture some aspects of Haskell types. They're useful if you are aware that they take you only so far. > > In your example, LayoutItem is a type name, while StaffItem and TextItem > > are constructor, that is functions. > > Saying that a function specializes a type is a bit of a stretch, I think > > ... > > > > Nevertheless, they can sometime be used to accomplish the same goal : > > where in OO you define an abstact class and then > > specialize with concrete classes to model a classification, in haskell > > you can define a data type with alternate constructors. > > > > I think that data types with alternate constructores are called > > algebraic data types in haskellese, but I'm not sure of that ... Yes, they're called algebraic datatypes, but I'm not sure if a type must have more than one constructor to qualify as such. > > Here's what I've learned from my investigations, but I welcome any > clarifications. > > There are a few ways they don't resemble constructors in OO, or unions in > C. > > They are "constructors", but also "take apart" the item in pattern > matching. myfunc (StaffItem pos dimension) = ... > myfunc (TextItem pos dimension) = ... > > You can also hide the constructors when you export a module. I could export > LayoutItem but not StaffItem and TextItem, meaning that other code would > see LayoutItem as a kind of abstract base class. > > When you name a field in each constructor (the same name), you can access > that field on any LayoutItem without knowing its constructor using the > accessor function for that field. This looks a lot like an abstract base > class. > > data LayoutItem = TextItem { myField :: Int } > > | StaffItem { myField :: Int } > > x1 = TextItem { myField = 3 } > x2 = STaffItem { myField = 4 } > > y1 = myField x1 > y2 = myField x2 > > When I tried to make TextItem and StaffItem instances of a class, I got an > error. They aren't really types. Only LayoutItem is the type. > > instance Eq TextItem where ... > ---> ERROR! > > instance Eq StaffItem where ... > > ---> ERROR! > > instance Eq LayoutItem where... > ---> ok > > Right now I'm just confused by how to translate an exising OO design. I'm > porting a partially complete Python program to Haskell. There are many > options. For instance I could set up a class called LayoutClass, make > TextItem and StaffItem their own classes and make them instances of the "their own types" > class. > > -- Note: Now I can no longer have any overlapping field names > data TextItem = TextItem { tField1, tField2 :: Int } > data StaffItem = StaffItem { sField1, sField3 :: Int } For fields that are generic enough to be interesting, you can have class HasPosition a where pos :: a -> Position class HasDimension a where dim :: a -> Dimension class HasField1 a where field1 :: a -> Int instance HasField1 TextItem where field1 (TextItem f1 _) = f1 > > class LayoutClass a where > access1 :: a -> Int > > instance LayoutClass TextItem where > access1 (TextItem t) = tField1 t > > instance LayoutClass StaffItem where > access1 (StaffItem s ) = sField1 s > > Or put everything in its own module and use qualified names. Probably the > best choice for future considerations. Consider also the "class HasWhatever" approach, sometimes it's better than qualified names. From allbery at ece.cmu.edu Tue Apr 7 13:31:40 2009 From: allbery at ece.cmu.edu (Brandon S. Allbery KF8NH) Date: Tue Apr 7 13:18:33 2009 Subject: [Haskell-beginners] accessor function scope In-Reply-To: <20090407130054.GD2207@colquitt.org> References: <49DAFA38.4020906@alumni.caltech.edu> <20090407130054.GD2207@colquitt.org> Message-ID: <4D6DE2F7-05D6-4437-9374-FAD93C71DC0F@ece.cmu.edu> On 2009 Apr 7, at 9:00, John Dorsey wrote: >> I've noticed that if I declare two types like this >> >> data Thing1 = Thing1 { itemPos :: Int } >> data Thing2 = Thing2 { itemPos :: Int } >> >> then I get the error "Multiple declarations of Main.itemPos" > > Here's something to consider. What's the type of itemPos? In the > above > code, it can't be > > itemPos :: Thing1 -> Int > > because you want to be able to apply it to a Thing2. I suppose the > compiler could, behind the scenes, create a typeclass like this: I think it already does this if you ask for the DisambiguateRecordFields language extension (provided it can tell which one is needed!). >> For that matter, I don't know what the term is for a "StaffItem-type >> LayoutItem". The type is clearly LayoutItem. "StaffItem" is the >> constructor. How do you refer to the concept of a LayoutItem >> constructed >> via a StaffItem? > > You can just call it "a StaffItem", I guess. I don't know if > there's a > common term. But you're right that it's type is LayoutItem. Technically LayoutItem is a sum of products and StaffItem is a variant (see http://en.wikipedia.org/wiki/Sum_type for more information). -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH -------------- next part -------------- A non-text attachment was scrubbed... Name: PGP.sig Type: application/pgp-signature Size: 195 bytes Desc: This is a digitally signed message part Url : http://www.haskell.org/pipermail/beginners/attachments/20090407/163e8167/PGP.bin From allbery at ece.cmu.edu Tue Apr 7 13:38:16 2009 From: allbery at ece.cmu.edu (Brandon S. Allbery KF8NH) Date: Tue Apr 7 13:25:08 2009 Subject: [Haskell-beginners] accessor function scope In-Reply-To: <200904071515.00936.daniel.is.fischer@web.de> References: <200904071515.00936.daniel.is.fischer@web.de> Message-ID: <055C6879-5AC7-4AC3-ACC8-0B01224C7CF3@ece.cmu.edu> On 2009 Apr 7, at 9:15, Daniel Fischer wrote: > Yes, they're called algebraic datatypes, but I'm not sure if a type > must have > more than one constructor to qualify as such. An ADT is any type expressible by a combination of sum and product types, IIRC. Single constructor types are product types, multiple constructors are sums of product types. (Note that this leaves out "data Nil"; that's why it's an extension. "data Nil = Nil" is vacuously an ADT.) -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH -------------- next part -------------- A non-text attachment was scrubbed... Name: PGP.sig Type: application/pgp-signature Size: 195 bytes Desc: This is a digitally signed message part Url : http://www.haskell.org/pipermail/beginners/attachments/20090407/9275ed20/PGP.bin From apfelmus at quantentunnel.de Tue Apr 7 19:29:22 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Tue Apr 7 19:16:29 2009 Subject: [Haskell-beginners] Re: CORRECTED: making translation from imperative code] In-Reply-To: <49D723C6.4070905@alumni.caltech.edu> References: <49D50B08.4080707@alumni.caltech.edu> <49D723C6.4070905@alumni.caltech.edu> Message-ID: Michael Mossey wrote: > Okay, I read all of your email, and there is one problem. My layout > problem is more complex than I communicated at first. Let me give a more > detailed example: > > staff 1: xxxx|xxxx x|x > staff 2: x|xx xxxx|xx > staff 3: x|x > a b c > > There are two additional concerns to what you coded up. Notice that > parts of events on different staves are allowed to overlap. To determine > the spacing from a to b, one has to know the widths of items on each > staff to see that they they can be placed with some overlap but won't > collide. They can't be treated strictly as a compound item and "going > blind" to the parts that make them up. > > Secondly, look at the item on staff 3 at c. It has no prior item to > avoid colliding with, and no items on other staves to line up with, but > there is still a constraint on its position: c > b (by some amount that > can be experimented with). No problem. :) Reading your code, I'd generally recommend a higher-level approach focusing on *abstraction*. Primitive recursion can do the job, but it's error-prone and tedious and best avoided. > -- Item is a pair giving left width and right width. > type Item = (Int, Int) > -- Chunk represents items that must align. > -- There may not be one on every staff, > -- hence the use of Maybe > type Chunk = [ Maybe Item ] Abstraction starts with using type synonyms like type Pos = Int type Width = Pos that indicate what the parameter denotes, not how it's represented by the computer. [Int] is less descriptive than [Pos] (a list of absolute coordinates), because it could also mean [Width] (a list of relative coordinates). For instance, it's possible to add two widths, but adding two positions should be a type error, you may only advance a position by a width. Also, I think that Chunk is too generic a name, but I don't have a good replacement for now. But see below. Abstraction is also key to solving the new problem description with the same algorithm as the old one. In particular, our goal is to implement the function align just like the old one. The core abstraction is that of an *extent*. It's simply a list of widths type Extent = [Width] representing a vertical group of bars. xxxx| |xxxx xx| or |xx = [4,2,3] xxx| |xxx We don't specify whether they are ragged to the right or left. The define the width of an extent to be the maximum width of its bars width :: Extent -> Width width = maximum A Chunk is of course just a pair of extents, one to the left and one to the right extents :: Chunk -> (Extent,Extent) extents = unzip . map (maybe (0,0) id) Now, align is structured just like before, calculating the gaps between different items align :: [(Extent, Extent)] -> [Pos] align xs = scanl (+) (width l) gaps where (l:ls, rs) = unzip xs gaps = zipWith fit rs ls However, extents are now fitted together with fit :: Extent -> Extent -> Width fit xs ys = (+1) . maximum . zipWith (+) xs ys The previous code can be interpreted as fitting extents together with fit xs ys = maximum xs + maximum ys Different definitions of fit yield different layouts algorithms. I'm not happy with the definition of align yet, because the specifics of laying out extents are present in two places, namely width and fit instead of just one, namely fit . This can be remedied by noting that the purpose of width is to fit the first extent to the *left boundary*. In other words, width = fit (repeat 0) (assuming that fit is able to crop and infinite list of widths to the proper size). Thus, we have align xs = scanl1 (+) gaps where (ls,rs) = unzip xs boundary = repeat 0 gaps = zipWith fit (boundary:rs) ls In the end, both align and your layout3 functions do exactly the same calculations, of course, but by virtue of abstraction, the correctness and structure of the former is self-evident. > layout3 :: [ Chunk ] -> [ Int ] > layout3 cs = layout3' cs (replicate (length cs) 0) 0 > > layout3' :: [ Chunk ] -> [ Int ] -> Int -> [ Int ] > layout3' [] _ _ = [] > layout3' (c:cs) rs minP = p : layout3' cs rs' (p + 1) where > p = maximum $ minP : (map place (zip c rs)) > rs' = map (advance p) c > place (item, r) = case item of > Just ( left, right ) -> r + left + 1 > _ -> 0 > advance p item = case item of > Just ( left, right ) -> p + right + 1 > _ -> p Two remarks on the code for pretty printing: > drawLayout :: [ Chunk ] -> [ Int ] -> String > drawLayout cs pos = unlines $ makeLines cs pos where > > makeLines :: [ Chunk ] -> [ Int ] -> [ String ] > makeLines cs@(cs1:_) pos > | null cs1 = [] > | otherwise = makeLine (map head cs) pos : > makeLines (map tail cs) pos This is basically a function known as transpose (from Data.List). Also, let's reorder the parameters. makeLines :: [Pos] -> [Chunk] -> [String] makeLines pos = map (makeLine pos) . transpose > makeLine :: [ Maybe Item ] -> [ Int ] -> String > makeLine items pos = foldl addItem [] (zip items pos) > > addItem :: String -> ( Maybe Item, Int ) -> String > addItem s ( item, p ) = > let le = length s in case item of > Just ( l, r ) -> s ++ (replicate (p - le - l) ' ') ++ > (replicate l 'x') ++ "|" ++ (replicate r 'x') > _ -> s > > data1 = [ [ Just (2,2), Just(1,1), Just (2,3 ) ], > [ Just (1,1), Just (3,4), Just(1,1) ], > [ Just (4,4), Nothing, Just (1,1) ] ] > > answer = drawLayout data1 (layout3 data1) > main = do putStr answer main = putStr answer -- no do required > *Main> main > xx|xx x|x xxxx|xxxx > x|x xxx|xxxx > xx|xxx x|x x|x > *Main> Regards, apfelmus -- http://apfelmus.nfshost.com From voigt at tcs.inf.tu-dresden.de Wed Apr 8 02:09:11 2009 From: voigt at tcs.inf.tu-dresden.de (Janis Voigtlaender) Date: Wed Apr 8 01:56:01 2009 Subject: [Haskell-beginners] Local Haskell meeting, Halle/Saale, Germany, June 12 Message-ID: <49DC3F87.4060406@tcs.inf.tu-dresden.de> [Apologies for German announcement text...] --------------------------------------------- HaL4 : Haskell - Tutorial + Workshop + Party am Freitag, dem 12. Juni 2009, in Halle/Saale --------------------------------------------- Das traditionsreiche HaL-Treffen bietet eine gute Mischung von Haskell-bezogenen Themen aus Forschung, Anwendung und Lehre mit vielen M?glichkeiten zu Diskussion und Unterhaltung bei der anschlie?enden Party. Der Workshop wird in diesem Jahr erg?nzt durch Tutorien f?r Haskell-Ein- und Umsteiger. Diesmal findet das Treffen in Halle/Saale im Institut f?r Informatik der Martin-Luther-Universit?t Halle-Wittenberg statt. Wir planen: 10 - 13 Uhr: Tutorien 15 - 19 Uhr: Fachvortr?ge 19 - 22 Uhr: Grillparty Wir freuen uns auf rege Teilnahme sowie spannende Vortr?ge mit hei?en Diskussionen und bitten um Vortragsanmeldungen bis zum 8. Mai. Gedacht sind 4 mal je 30 min Vortrag + 30 min Diskussion. Weitere Informationen auf http://www.iba-cg.de/hal4.html -- Dr. Janis Voigtlaender http://wwwtcs.inf.tu-dresden.de/~voigt/ mailto:voigt@tcs.inf.tu-dresden.de From iand675 at gmail.com Wed Apr 8 11:30:20 2009 From: iand675 at gmail.com (Ian Duncan) Date: Wed Apr 8 11:17:13 2009 Subject: [Haskell-beginners] runghc question Message-ID: I'm writing a script for TextMate using Haskell, and I don't know how to get it to work with runghc. Here's the script: #!/usr/local/bin/runghc >module Main >where >import System.Cmd >main = putStrLn "FOO" {- do c <- getContents system ("/Users/ian/.cabal/bin/pointfree \"" ++ c ++ "\"") -} How do I get it to treat this as an lhs file rather than an hs file if there is no extension to the filename? Is there an argument for this? Ian Duncan From jason.dusek at gmail.com Wed Apr 8 12:05:31 2009 From: jason.dusek at gmail.com (Jason Dusek) Date: Wed Apr 8 11:52:21 2009 Subject: [Haskell-beginners] runghc question In-Reply-To: References: Message-ID: <42784f260904080905u17e7c099uf4e2e8daeda3ae35@mail.gmail.com> Perhaps `-x` ? -x suffix Override default behaviour for source files -- Jason Dusek From mpm at alumni.caltech.edu Wed Apr 8 12:24:52 2009 From: mpm at alumni.caltech.edu (Michael P Mossey) Date: Wed Apr 8 12:11:41 2009 Subject: [Haskell-beginners] a better way to do this Message-ID: <49DCCFD4.5030008@alumni.caltech.edu> This is an early attempt to create some kind of parser, for text that is xml-like but not actually xml. This is probably a disaster by Haskell standards... If someone could point me in the direction of a better way of doing things, that would be great. I don't want to use the existing parser library, not at first, because I want to learn more from first principles (for now). The input looks something like: thingy other thingy ... ... where there are any number of entries. Each entry consists of a varied number of named fields. For now, the named fields can be anything--any names, in any order. Later I'll do sanity checking to ensure the right fields are there, to provide default values, etc. This uses Data.Bytestring.Char8 for efficiency processing large files. The output types are as follows: type Bs = B.ByteString -- alias type Component = ( Bs, Bs ) -- one named field type Entry = [ Component ] -- all named fields in one entry type Doc = [ Entry ] -- all entries in the input document The basic strategy is to create parsing functions, which take in a string (actually ByteString), and return an object, the remainder of the string, and an index. (The index indicates the position of the first character in the remainder of the string, which is useful for giving error messages.) Top level function is called parseReqs ( "parse requirements" -- this is actually going to be used for a software requirements management project). Here's the rest of the code: -- types for regular expression matching type Re3 = ( Bs, Bs, Bs ) type Re4 = ( Bs, Bs, Bs, [ Bs ] ) parseReqs :: Bs -> ( Doc, Bs, Int ) parseReqs buf = parseReqs' buf 0 parseReqs' :: Bs -> Int -> ( Doc, Bs, Int ) parseReqs' buf idx | B.null buf = ( [], buf, idx ) | otherwise = case parseEntry buf idx of (Just e, rem, remIdx) -> let ( doc, rem', remIdx' ) = parseReqs' rem remIdx in ( e : doc, rem', remIdx' ) (Nothing, rem, remIdx ) -> ( [], rem, remIdx ) parseEntry :: Bs -> Int -> ( Maybe Entry, Bs, Int ) parseEntry buf idx = let ( before, match, after ) = buf =~ "" :: Re3 idx' = idx + B.length before + B.length match in if B.null match then ( Nothing, after, idx' ) else let ( e, after', idx'' ) = parseEntryBody after idx' in ( Just e, after', idx'' ) parseEntryBody :: Bs -> Int -> ( Entry, Bs, Int ) parseEntryBody buf idx = let ( before, match, after ) = buf =~ "" :: Re3 idx' = idx + B.length before + B.length match in if B.null match then error "Missing " else -- Note: index passed to parseEntryComponents is same as one passed -- into this function, because we pass 'before' to -- parseEntryComponents. Index returned from from this function is -- the one calculated above to occur at the start of 'after' ( parseEntryComponents before idx, after, idx' ) parseEntryComponents :: Bs -> Int -> Entry parseEntryComponents buf idx = let ( before, match, after, groups ) = buf =~ B.pack "<([^>]+)>" :: Re4 idx' = idx + B.length before + B.length match in if B.null match then [] else let ( component, buf', idx'' ) = parseCompBody (head groups) after idx' components = parseEntryComponents buf' idx'' in component : components parseCompBody :: Bs -> Bs -> Int -> ( Component, Bs, Int ) parseCompBody compName buf idx = let ( before, match, after ) = buf =~ (B.pack "") :: Re3 idx' = idx + B.length before + B.length match in if B.null match then error ("No ending to component " ++ B.unpack compName) else ( ( compName, before ), after, idx' ) From marcot at holoscopio.com Wed Apr 8 18:29:24 2009 From: marcot at holoscopio.com (Marco =?ISO-8859-1?Q?T=FAlio?= Gontijo e Silva) Date: Wed Apr 8 18:16:29 2009 Subject: [Haskell-beginners] Inferred type is less polymorphic than e Message-ID: <1239229764.6067.86.camel@zezinho> Hello, I'm getting this error message from GHC in the following code: > type M a = Monad m => m a > class A a b where > f :: Monad m => a -> m b > instance A String Char where > f string = return $ head string > instance A Char Int where > f int = return $ fromEnum int I thought at first to write h like this, but it gives me the error. If I write it like the other h uncommented, there's no error. I can't see why they aren't equivalent. h :: IO () h = f "abc" >>= (f :: Char -> M Int) >>= print > h :: IO () > h = (f "abc" :: M Char) >>= f >>= (print :: Int -> IO ()) Can someone clarify this to me? Greetings. -- marcot http://marcot.iaaeee.org/ From daniel.is.fischer at web.de Wed Apr 8 19:55:22 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Wed Apr 8 19:42:19 2009 Subject: [Haskell-beginners] Inferred type is less polymorphic than e In-Reply-To: <1239229764.6067.86.camel@zezinho> References: <1239229764.6067.86.camel@zezinho> Message-ID: <200904090155.23526.daniel.is.fischer@web.de> Am Donnerstag 09 April 2009 00:29:24 schrieb Marco T?lio Gontijo e Silva: > Hello, > > I'm getting this error message from GHC in the following code: > > type M a = Monad m => m a > > > > class A a b where > > f :: Monad m => a -> m b > > > > instance A String Char where > > f string = return $ head string > > > > instance A Char Int where > > f int = return $ fromEnum int > > I thought at first to write h like this, but it gives me the error. If > I write it like the other h uncommented, there's no error. I can't see > why they aren't equivalent. > > h :: IO () > h = f "abc" >>= (f :: Char -> M Int) >>= print > > > h :: IO () > > h = (f "abc" :: M Char) >>= f >>= (print :: Int -> IO ()) > > Can someone clarify this to me? > > Greetings. The first error message when loading that code is Inferred.hs:3:0: Illegal polymorphic or qualified type: forall (m :: * -> *). (Monad m) => m a Perhaps you intended to use -XRankNTypes or -XRank2Types In the type synonym declaration for `M' That can be a hint. The type synonym M is probably not what you think. This: ---------------------------------------------------------------- class B a b where foo :: a -> M b instance B String Char where foo str = return $ head str instance B Char Int where foo c = return $ fromEnum c k :: IO () k = foo "abc" >>= (foo :: Char -> M Int) >>= print ---------------------------------------------------------------- works, as does m = foo "abc" >>= (foo :: Char -> (forall x. Monad x => x Int)) >>= print And that reveals what's going on, since m is in fact the same as k. The type of f in class A says that given any specific monad m and a value of type a, f can produce a value of type m b. But when you write (f :: Char -> M Int) , you say that given a Char, f produces a value which belongs to m Int *for every monad m*. Thus the type you state for f (the expected type) is more polymorphic than the actual type f has according to the class definition (which is the inferred type). From mpm at alumni.caltech.edu Wed Apr 8 20:07:35 2009 From: mpm at alumni.caltech.edu (Michael P Mossey) Date: Wed Apr 8 19:54:31 2009 Subject: [Haskell-beginners] a better way to do this In-Reply-To: <49DCCFD4.5030008@alumni.caltech.edu> References: <49DCCFD4.5030008@alumni.caltech.edu> Message-ID: <49DD3C47.1030505@alumni.caltech.edu> Michael P Mossey wrote: > This is an early attempt to create some kind of parser, for text that is > xml-like but not actually xml. This is probably a disaster by Haskell > standards... If someone could point me in the direction of a better way > of doing things, that would be great. I don't want to use the existing > parser library, not at first, because I want to learn more from first > principles (for now). > To follow up my own post, I'm working through chapter 10 of "Real World Haskell" right now, and then I'll look at chapter 14 (Monads). I think this is a better way of creating parsers. Maybe I'll look at Parsec eventually too, although I want to do a lot of stuff myself for the learning exprience. Thanks, Mike From emmanuel.delaborde at cimex.com Thu Apr 9 05:33:35 2009 From: emmanuel.delaborde at cimex.com (emmanuel.delaborde) Date: Thu Apr 9 05:20:22 2009 Subject: [Haskell-beginners] STM and IO Message-ID: Hello list I am trying to use STM for shared access to a file I first used a TVar to to accumulate the text returned by the threads and write TVar's content to a file after a delay (how do you ensure all threads have terminated by the way, that would be more robust than using an arbitrary delay) -- this works main = do let fname = "store.txt" store <- atomically $ newTVar "" forkIO $ 10 `replicateM_` (thread store) threadDelay 800000 txt <- atomically (readTVar store) writeFile fname txt thread :: TVar (String) -> IO () thread store = atomically ( readTVar store >>= writeTVar store . (++ " some text ")) But when I try to concurrently write to the file, I get into troubles. I keep the file handle in a TMVar, hoping than just one thread at a time will be able to use that handle but nothing gets written to "store.txt" ? Is my IO too lazy ? -- this does not work main = do let fname = "store.txt" fh <- openFile fname ReadWriteMode store <- atomically $ newTMVar fh forkIO $ 10 `replicateM_` (writeTo store) writeTo :: TMVar (Handle) -> IO () writeTo store = do fh <- atomically $ takeTMVar store text <- hGetContents fh hPutStr fh (text ++ " some text ") atomically $ putTMVar store fh Thank you -- Emmanuel Delaborde ----------------------------------------------------------------------------------------------- This e-mail (and any attachments) is confidential and may contain personal views which are not the views of Cimex Media Ltd and any affiliated companies, unless specifically stated. It is intended for the use of the individual or group to whom it is addressed. If you have received it in error, please delete it from your system, do not use, copy or disclose the information in any way nor act in reliance on it and please notify postmaster@cimex.com A company registered in England Wales. Company Number 03765711 Registered Office : The Olde Bakehouse, 156 Watling Street East, Towcester, Northants NN12 6DB This email was scanned by Postini, the leading provider in Managed Email Security. From quentin.moser at unifr.ch Thu Apr 9 06:03:03 2009 From: quentin.moser at unifr.ch (Quentin Moser) Date: Thu Apr 9 05:49:08 2009 Subject: [Haskell-beginners] STM and IO In-Reply-To: References: Message-ID: <20090409120303.5382681e@unifr.ch> On Thu, 9 Apr 2009 10:33:35 +0100 "emmanuel.delaborde" wrote: > Hello list > > I am trying to use STM for shared access to a file > > I first used a TVar to to accumulate the text returned by the threads > and write TVar's content to a file after a delay (how do you ensure > all threads have terminated by the way, that would be more robust > than using an arbitrary delay) > > > -- this works > main = do > let fname = "store.txt" > store <- atomically $ newTVar "" > forkIO $ 10 `replicateM_` (thread store) > threadDelay 800000 > txt <- atomically (readTVar store) > writeFile fname txt > > thread :: TVar (String) -> IO () > thread store = atomically ( readTVar store >>= writeTVar store . (++ > " some text ")) > > > But when I try to concurrently write to the file, I get into troubles. > I keep the file handle in a TMVar, hoping than just one thread at a > time will be able to use that handle > but nothing gets written to "store.txt" ? Is my IO too lazy ? > > > -- this does not work > main = do > let fname = "store.txt" > fh <- openFile fname ReadWriteMode > store <- atomically $ newTMVar fh > forkIO $ 10 `replicateM_` (writeTo store) > > writeTo :: TMVar (Handle) -> IO () > writeTo store = do > fh <- atomically $ takeTMVar store > text <- hGetContents fh > hPutStr fh (text ++ " some text ") > atomically $ putTMVar store fh > > > Thank you > Your problem has nothing to do with lazyness; Haskell simply kills all other threads when the main thread returns from main. You have to somehow wait for them to complete in main or they won't have time to run. As strange as it seems, I don't think the standard libraries provide an easy way to do this, but you can implement it yourself. Here's an example inspired by the documentation of Control.Concurrent: > import Control.Concurrent > import Control.Exception (finally) > > myFork :: IO () -> IO (MVar ()) > myFork a = do v <- newEmptyMVar > a `finally` (putMVar v ()) > > myWait :: MVar () -> IO () > myWait = readMVar With this, you could rewrite your main like this: > main = do > let fname = "store.txt" > fh <- openFile fname ReadWriteMode > store <- atomically $ newTMVar fh > waitMe <- myFork $ 10 `replicateM_` (writeTo store) > myWait waitMe Now onto the second problem: ignore me if I'm wrong, but it seems your intent is to spawn 10 threads that will each try to run (writeTo store) once. What your current code does is spawn one thread that sequentially runs writeTo 10 times. To create 10 threads, you should fork inside the replicateM, not outside. Here's how you could correct this (again using myFork and myWait from above): > main = do > let fname = "store.txt" > fh <- openFile fname ReadWriteMode > store <- atomically $ newTMVar fh > waitMes <- 10 `replicateM` (myFork $ writeTo store)) > mapM_ myWait waitMes (make sure you use replicateM and not replicateM_ or you'll get a type error) Note: I haven't tried running any of this code, but it seems simple enough to be confident in. From quentin.moser at unifr.ch Thu Apr 9 06:16:54 2009 From: quentin.moser at unifr.ch (Quentin Moser) Date: Thu Apr 9 06:03:00 2009 Subject: [Haskell-beginners] STM and IO In-Reply-To: <20090409120303.5382681e@unifr.ch> References: <20090409120303.5382681e@unifr.ch> Message-ID: <20090409121654.35d07bdd@unifr.ch> On Thu, 9 Apr 2009 12:03:03 +0200 Quentin Moser wrote: > Here's an example inspired by the documentation of Control.Concurrent: > > > import Control.Concurrent > > import Control.Exception (finally) > > > > myFork :: IO () -> IO (MVar ()) > > myFork a = do v <- newEmptyMVar > > a `finally` (putMVar v ()) > > > > myWait :: MVar () -> IO () > > myWait = readMVar Oops, my code is completely messed up. Here's a correct version: > myFork a = do v <- newEmptyMVar > forkIO $ a `finally` putMVar v () > return v > myWait = readMVar >> return () From marcot at holoscopio.com Thu Apr 9 07:16:01 2009 From: marcot at holoscopio.com (Marco =?ISO-8859-1?Q?T=FAlio?= Gontijo e Silva) Date: Thu Apr 9 07:03:10 2009 Subject: [Haskell-beginners] Inferred type is less polymorphic than e In-Reply-To: <200904090155.23526.daniel.is.fischer@web.de> References: <1239229764.6067.86.camel@zezinho> <200904090155.23526.daniel.is.fischer@web.de> Message-ID: <1239275761.6067.101.camel@zezinho> Em Qui, 2009-04-09 ?s 01:55 +0200, Daniel Fischer escreveu: > Am Donnerstag 09 April 2009 00:29:24 schrieb Marco T?lio Gontijo e Silva: > > Hello, > > > > I'm getting this error message from GHC in the following code: > > > type M a = Monad m => m a > > > > > > class A a b where > > > f :: Monad m => a -> m b > > > > > > instance A String Char where > > > f string = return $ head string > > > > > > instance A Char Int where > > > f int = return $ fromEnum int > > > > I thought at first to write h like this, but it gives me the error. If > > I write it like the other h uncommented, there's no error. I can't see > > why they aren't equivalent. > > > > h :: IO () > > h = f "abc" >>= (f :: Char -> M Int) >>= print > > > > > h :: IO () > > > h = (f "abc" :: M Char) >>= f >>= (print :: Int -> IO ()) > > > ---------------------------------------------------------------- > class B a b where > foo :: a -> M b > > instance B String Char where > foo str = return $ head str > > instance B Char Int where > foo c = return $ fromEnum c > > k :: IO () > k = foo "abc" >>= (foo :: Char -> M Int) >>= print > ---------------------------------------------------------------- > > works, as does > > m = foo "abc" >>= (foo :: Char -> (forall x. Monad x => x Int)) >>= print > > And that reveals what's going on, since m is in fact the same as k. > The type of f in class A says that given any specific monad m and a value of > type a, f can produce a value of type m b. > But when you write > (f :: Char -> M Int) > , you say that given a Char, f produces a value which belongs to m Int *for > every monad m*. Thus the type you state for f (the expected type) is more > polymorphic than the actual type f has according to the class definition (which > is the inferred type). Ok, I got it, so I tried changing class A in my example to: > class A a b where > f :: forall m . Monad m => a -> m b so that the type of f would be as polymorphic as the type a -> M b. But I got the same problem. Your solution is good, but I can't do it in my real application where I find out this problem, because the type synonym M is defined after the class A, and it contains more than on type constraint: > type Interpret value > = ( MonadReader Input monad > , MonadState Machine monad > , MonadWriter Stream monad) > => monad value My use is that I have some classes defined in modules included by the one that defines type Interpret, like this: > class Value pointer value where > getValue > :: (MonadReader Program monad, MonadState Machine monad) > => pointer -> monad value And even if they were defined in the same file, it would not be good to define them as Interpret, because it would restrict its type. Another thing: I understand your explanation, but I don't get why this makes the other h definition valid. Could you clarify me on that? Thanks. -- marcot http://marcot.iaaeee.org/ From daniel.is.fischer at web.de Thu Apr 9 10:52:25 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Thu Apr 9 10:39:21 2009 Subject: [Haskell-beginners] Inferred type is less polymorphic than e In-Reply-To: <1239275761.6067.101.camel@zezinho> References: <1239229764.6067.86.camel@zezinho> <200904090155.23526.daniel.is.fischer@web.de> <1239275761.6067.101.camel@zezinho> Message-ID: <200904091652.25742.daniel.is.fischer@web.de> Am Donnerstag 09 April 2009 13:16:01 schrieb Marco T?lio Gontijo e Silva: > Em Qui, 2009-04-09 ?s 01:55 +0200, Daniel Fischer escreveu: > Ok, I got it, so I tried changing class A in my example to: > > class A a b where > > f :: forall m . Monad m => a -> m b > > so that the type of f would be as polymorphic as the type a -> M b. But > I got the same problem. Because that's exactly the same type f had before. To get a polymorphic result from f, you have to declare {-# LANGUAGE Rank2Types #-} -- or make it RankNTypes and be ready for more quantification class A a b where f :: a -> (forall m. Monad m => m b) > > Your solution is good, but I can't do it in my real application where I > find out this problem, because the type synonym M is defined after the > > class A, and it contains more than on type constraint: > > type Interpret value > > = ( MonadReader Input monad > > , MonadState Machine monad > > , MonadWriter Stream monad) > > => monad value > > My use is that I have some classes defined in modules included by the > > one that defines type Interpret, like this: > > class Value pointer value where > > getValue > > > > :: (MonadReader Program monad, MonadState Machine monad) > > > > => pointer -> monad value > > And even if they were defined in the same file, it would not be good to > define them as Interpret, because it would restrict its type. > > Another thing: I understand your explanation, but I don't get why this > makes the other h definition valid. Could you clarify me on that? This definition? > > > h :: IO () > > > h = (f "abc" :: M Char) >>= f >>= (print :: Int -> IO ()) Let's start on the left: (f "abc" :: M Char) === (f "abc" :: forall m. Monad m => m Char) Now we have class A a b where f :: Monad m => a -> m b instance A String Char where ... We apply f to the String "abc", so an "instance A String b" has to be selected. f will here be invoked at the type (A String b, Monad m) => String -> m b === forall m b. (A String b, Monad m) => String -> m b Therefore f "abc" has the type resulting from removing the argument type, namely f "abc" :: forall m b. (A String b, Monad m) => m b Note that although f does not have the type (A String b) => String -> (forall m. Monad m => m b) the expression (f string) has the type forall b m. (A String b, Monad m) => m b. It's the same with return, the type of return is forall a m. Monad m => a -> m a and not forall a. a -> (forall m. Monad m => m a), but the type of return value is (forall m. Monad m => m a), where a is the type of value. Now f "abc" has a type annotation, f "abc" :: M Char, or f "abc" :: forall m. Monad m => m Char That type must now be unified with the inferred type, forall mon b. (A String b, Monad mon) => mon b. It is obvious that we must have b === Char, so the compiler looks for an instance A String Char where... (or a more general instance) Since there is one, that is fine and the satisfied constraint (A String Char) can be removed. The two type(-constructor) variables m and mon are now unified and there contexts united. Since both contexts are the same, the result is f "abc" :: forall m. Monad m => m Char, exactly the specified signature (can't be anything else, if the inferred type were less polymorphic than the specified, it wouldn't compile, if it's more general, it's restricted to the specified type). On to the next step, look at (f "abc" :: M Char) >>= f (>>=) :: Monad m => m u -> (u -> m v) -> m v (f "abc") :: Monad mo => mo Char f :: (A a b, Monad mon) => a -> mon b Now we have to unify mo Char with m u (the contexts Monad m and Monad mo will be taken care of thereafter). That's easy, u == Char and m === mo, contexts are the same, so ((f "abc" :: M Char) >>=) :: Monad m => (Char -> m v) -> m v Next we must unify Char -> m v with a -> mon b. That's again easy, a === Char, mon === m, b === v. Now take the contexts (Monad m) and (A a b, Monad mon) into account. Substituting int f's context, we get the context (A Char v, Monad m) for f's type here, so this f is called at the type (A Char v, Monad m) => Char -> m v, and we get the type (f "abc" :: M Char) >>= f :: (A Char v, Monad m) => m v Finally, left :: (A Char v, Monad m) => m v (>>=) :: Monad mo => mo a -> (a -> mo b) -> mo b print :: Int -> IO () -- specified We get the type (left >>=) :: (A Char v, Monad m) => (v -> m b) -> m b and then must unify (v -> m b) with (Int -> IO ()), giving v === Int, m === IO, b === (). Substituting into the contexts gives (left >>= print) :: (A Char Int, Monad IO) => IO () The context doesn't contain any type variables and the conditions are fulfilled, so the context is removed, leaving (f "abc" :: M Char) >>= f >>= (print :: Int -> IO ()) :: IO (). > > Thanks. From emmanuel.delaborde at cimex.com Thu Apr 9 12:20:19 2009 From: emmanuel.delaborde at cimex.com (emmanuel.delaborde) Date: Thu Apr 9 12:07:14 2009 Subject: [Haskell-beginners] STM and IO In-Reply-To: <20090409094909.0C9E7324A12@www.haskell.org> References: <20090409094909.0C9E7324A12@www.haskell.org> Message-ID: > > From: Quentin Moser > Subject: Re: [Haskell-beginners] STM and IO > > Your problem has nothing to do with lazyness; Haskell simply kills all > other threads when the main thread returns from main. You have to > somehow wait for them to complete in main or they won't have time to > run. Doh! I've been bitten before... > Now onto the second problem: ignore me if I'm wrong, but it seems your > intent is to spawn 10 threads that will each try to run (writeTo > store) > once. What your current code does is spawn one thread that > sequentially > runs writeTo 10 times. yes you are right of course > Note: I haven't tried running any of this code, but it seems simple > enough to be confident in. I had to make a change to myFork to get it to compile, here's what I have now: module Main where import Control.Monad import Control.Concurrent import Control.Concurrent.STM import System.IO import Control.Exception (finally) myFork :: IO () -> IO (MVar ()) myFork a = do v <- newEmptyMVar a `finally` (putMVar v ()) return v -- to honor the return type myWait :: MVar () -> IO () myWait = readMVar main = do let fname = "store.txt" fh <- openFile fname ReadWriteMode store <- atomically $ newTMVar fh waitMes <- 10 `replicateM` (myFork $ writeTo store) mapM_ myWait waitMes writeTo :: TMVar (Handle) -> IO () writeTo store = do fh <- atomically $ takeTMVar store text <- hGetContents fh hPutStr fh (text ++ " some text ") atomically $ putTMVar store fh Now I get the following error : test3: store.txt: hPutStr: illegal operation (handle is closed) reading the doc about hGetContents, I found that : "Computation hGetContents hdl returns the list of characters corresponding to the unread portion of the channel or file managed by hdl, which is put into an intermediate state, semi-closed. In this state, hdl is effectively closed" Intuitively I'd want to write something like : writeTo filename = atomically (do { s <- readFile filename ; writeFile filename (s ++ "blah") }) but the type system prevents me from doing IO within STM I do not know how to go about sharing access to a file between multiple threads using STM... any pointers ? Thanks E. -- Emmanuel Delaborde Web Technologist Cimex 53-55 Scrutton Street, London UK, EC2A 4PJ T: +44 (0)20 7324 7780 F: +44 (0)20 7324 7781 http://www.cimex.com ----------------------------------------------------------------------------------------------- This e-mail (and any attachments) is confidential and may contain personal views which are not the views of Cimex Media Ltd and any affiliated companies, unless specifically stated. It is intended for the use of the individual or group to whom it is addressed. If you have received it in error, please delete it from your system, do not use, copy or disclose the information in any way nor act in reliance on it and please notify postmaster@cimex.com A company registered in England Wales. Company Number 03765711 Registered Office : The Olde Bakehouse, 156 Watling Street East, Towcester, Northants NN12 6DB This email was scanned by Postini, the leading provider in Managed Email Security. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090409/4a6d0b40/attachment.htm From cgrebeld at gmail.com Thu Apr 9 13:56:23 2009 From: cgrebeld at gmail.com (Chris G) Date: Thu Apr 9 13:43:09 2009 Subject: [Haskell-beginners] STM and IO In-Reply-To: References: <20090409094909.0C9E7324A12@www.haskell.org> Message-ID: <115f82830904091056q47ea50abobfb4dd2d643bbcef@mail.gmail.com> Since the file handle is closed after you read the contents, you need to open a new one before writing to it. On Thu, Apr 9, 2009 at 12:20 PM, emmanuel.delaborde < emmanuel.delaborde@cimex.com> wrote: > > From: Quentin Moser > Subject: Re: [Haskell-beginners] STM and IO > > Your problem has nothing to do with lazyness; Haskell simply kills all > other threads when the main thread returns from main. You have to > somehow wait for them to complete in main or they won't have time to > run. > > > Doh! > I've been bitten before... > > Now onto the second problem: ignore me if I'm wrong, but it seems your > intent is to spawn 10 threads that will each try to run (writeTo store) > once. What your current code does is spawn one thread that sequentially > runs writeTo 10 times. > > > yes you are right of course > > Note: I haven't tried running any of this code, but it seems simple > enough to be confident in. > > > I had to make a change to myFork to get it to compile, here's what I have > now: > > module Main where > > import Control.Monad > import Control.Concurrent > import Control.Concurrent.STM > import System.IO > import Control.Exception (finally) > > myFork :: IO () -> IO (MVar ()) > myFork a = do > v <- newEmptyMVar > a `finally` (putMVar v ()) > return v -- to honor the return type > > myWait :: MVar () -> IO () > myWait = readMVar > > main = do > let fname = "store.txt" > fh <- openFile fname ReadWriteMode > store <- atomically $ newTMVar fh > waitMes <- 10 `replicateM` (myFork $ writeTo store) > mapM_ myWait waitMes > > writeTo :: TMVar (Handle) -> IO () > writeTo store = do > fh <- atomically $ takeTMVar store > text <- hGetContents fh > hPutStr fh (text ++ " some text ") > atomically $ putTMVar store fh > > Now I get the following error : test3: store.txt: hPutStr: illegal > operation (handle is closed) > > reading the doc about hGetContents, I found that : "Computation > hGetContents hdl returns the list of characters corresponding to the unread > portion of the channel or file managed by hdl, which is put into an > intermediate state, semi-closed. In this state, hdl is effectively closed" > > > Intuitively I'd want to write something like > : writeTo filename = atomically (do { s <- readFile filename ; > writeFile filename (s ++ "blah") }) > but the type system prevents me from doing IO within STM > I do not know how to go about sharing access to a file between multiple > threads using STM... any pointers ? > > Thanks > > E. > > > > > > > > > > -- > Emmanuel Delaborde > Web Technologist > Cimex > 53-55 Scrutton Street, London UK, EC2A 4PJ > T: +44 (0)20 7324 7780 > F: +44 (0)20 7324 7781 > http://www.cimex.com > > ----------------------------------------------------------------------------------------------- > > This e-mail (and any attachments) is confidential and may contain > personal views which are not the views of Cimex Media Ltd and > any affiliated companies, unless specifically stated. It is intended > for the use of the individual or group to whom it is addressed. If > you have received it in error, please delete it from your system, > do not use, copy or disclose the information in any way nor act in > reliance on it and please notify postmaster@cimex.com > > A company registered in England Wales. Company Number 03765711 > Registered Office : The Olde Bakehouse, 156 Watling Street East, Towcester, > Northants NN12 6DB > > This email was scanned by Postini, the leading provider in Managed Email Security. > > > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090409/d8a52eba/attachment-0001.htm From apfelmus at quantentunnel.de Thu Apr 9 21:01:20 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Thu Apr 9 20:48:22 2009 Subject: [Haskell-beginners] Re: a better way to do this In-Reply-To: <49DD3C47.1030505@alumni.caltech.edu> References: <49DCCFD4.5030008@alumni.caltech.edu> <49DD3C47.1030505@alumni.caltech.edu> Message-ID: Michael P Mossey wrote: > Michael P Mossey wrote: >> This is an early attempt to create some kind of parser, for text that >> is xml-like but not actually xml. This is probably a disaster by >> Haskell standards... If someone could point me in the direction of a >> better way of doing things, that would be great. I don't want to use >> the existing parser library, not at first, because I want to learn >> more from first principles (for now). >> > > To follow up my own post, I'm working through chapter 10 of "Real World > Haskell" right now, and then I'll look at chapter 14 (Monads). I think > this is a better way of creating parsers. Maybe I'll look at Parsec > eventually too, although I want to do a lot of stuff myself for the > learning exprience. I don't think that doing it "the hard way by hand" is very enlightening, especially since you are using regular expressions anyway. (By the way, the latter are a niche in Haskell; any serious and also most non-serious parsing tasks are best done with parser combinators. The popularity of regular expressions in languages like Python or Perl is mainly due to the lack of more general parsing abstractions in these languages.) A much more rewarding introduction to parsing and parser combinators is probably to understand and experiment with their implementations, for instance by starting with Graham Hutton, Erik Meijer. Monadic Parser Combinators. http://www.cs.nott.ac.uk/~gmh/monparsing.ps Regards, apfelmus -- http://apfelmus.nfshost.com From calpaterson at googlemail.com Fri Apr 10 07:22:06 2009 From: calpaterson at googlemail.com (Cal Paterson) Date: Fri Apr 10 07:10:49 2009 Subject: [Haskell-beginners] Cabal install fails to download packages Message-ID: <20090410112206.GA11571@romeo> Hello, I am new to haskell, and I'm trying to get cabal to download and install packages for me. However, it seems to fail to download packages. Having cabal act on already installed packages seems to work fine. Here is the end of the output: cal@romeo:~$ cabal install haddock ... selecting unix-2.3.0.0 (installed) selecting ghc-paths-0.1.0.5 (hackage) and discarding ghc-paths-0.1, 0.1.0.1, 0.1.0.2, 0.1.0.3 and 0.1.0.4 In order, the following would be installed: ghc-paths-0.1.0.5 (new package) haddock-2.4.2 (new package) Downloading ghc-paths-0.1.0.5... GET http://hackage.haskell.org/packages/archive/ghc-paths/0.1.0.5/ghc-paths-0.1.0.5.tar.gz Sending: GET /packages/archive/ghc-paths/0.1.0.5/ghc-paths-0.1.0.5.tar.gz HTTP/1.1 User-Agent: cabal-install/0.6.2 Host: hackage.haskell.org proxy uri host: , port: Creating new connection to cabal: Error: some packages failed to install: ghc-paths-0.1.0.5 failed while downloading the package. haddock-2.4.2 depends on ghc-paths-0.1.0.5 which failed to install. I first guessed that cabal was tripping up over some environment variable, but it seems that $http_proxy is unset: cal@romeo:~$ set | grep -i http | xclip http_proxy= Can anyone provide some advice as to what is likely to be going wrong? Thanks, Cal From aditya.siram at gmail.com Fri Apr 10 17:06:54 2009 From: aditya.siram at gmail.com (aditya siram) Date: Fri Apr 10 16:53:36 2009 Subject: [Haskell-beginners] rts package in an invalid state Message-ID: <594f78210904101406y6b2999d3ucb132d56d63cb129@mail.gmail.com> Hi all, I recently compiled and installed ghc 6.10.2 on a clean system. But a 'ghc-pkg check' shows an error with the rts package [1]. A google search advised me to install libffi5. I did this but keep getting the same error. Any ideas? Thanks ... deech [1] http://hpaste.org/fastcgi/hpaste.fcgi/view?id=3630#a3630 From jason.dusek at gmail.com Fri Apr 10 18:40:15 2009 From: jason.dusek at gmail.com (Jason Dusek) Date: Fri Apr 10 18:26:56 2009 Subject: [Haskell-beginners] rts package in an invalid state In-Reply-To: <594f78210904101406y6b2999d3ucb132d56d63cb129@mail.gmail.com> References: <594f78210904101406y6b2999d3ucb132d56d63cb129@mail.gmail.com> Message-ID: <42784f260904101540o9f05e1akf1652dce8c5a5ece@mail.gmail.com> Oh, look at this: http://www.nabble.com/ghc-pkg-check-problem-in-6.10.2-td22846037.html Seems to have come up not too long ago. -- Jason Dusek From aditya.siram at gmail.com Fri Apr 10 19:01:45 2009 From: aditya.siram at gmail.com (aditya siram) Date: Fri Apr 10 18:48:26 2009 Subject: [Haskell-beginners] rts package in an invalid state In-Reply-To: <42784f260904101540o9f05e1akf1652dce8c5a5ece@mail.gmail.com> References: <594f78210904101406y6b2999d3ucb132d56d63cb129@mail.gmail.com> <42784f260904101540o9f05e1akf1652dce8c5a5ece@mail.gmail.com> Message-ID: <594f78210904101601m7e7185aeg196cc05998ca135c@mail.gmail.com> Yes, this was it! Thanks for much! -deech On Fri, Apr 10, 2009 at 5:40 PM, Jason Dusek wrote: > ?Oh, look at this: > > ? ?http://www.nabble.com/ghc-pkg-check-problem-in-6.10.2-td22846037.html > > ?Seems to have come up not too long ago. > > -- > Jason Dusek > From kscraja at gmail.com Fri Apr 10 21:55:37 2009 From: kscraja at gmail.com (Raja Koduru) Date: Fri Apr 10 21:42:20 2009 Subject: [Haskell-beginners] rts package in an invalid state In-Reply-To: <594f78210904101601m7e7185aeg196cc05998ca135c@mail.gmail.com> References: <594f78210904101406y6b2999d3ucb132d56d63cb129@mail.gmail.com> <42784f260904101540o9f05e1akf1652dce8c5a5ece@mail.gmail.com> <594f78210904101601m7e7185aeg196cc05998ca135c@mail.gmail.com> Message-ID: <1336aed20904101855i34a2b544n13571524ad697332@mail.gmail.com> Hi, Just did ghc-pkg check on my system just out of curiosity. Even here I am getting the rts package errors. But I followed the instructions given at the above url to rectify it. To my surprise there is one more such error. It is related to haddock-2.4.2. Pasting here the 'ghc-pkg check's dump ---------------------------------------------------------------------------------------------------------------------------------------------------- C:\Program Files\Haskell>ghc-pkg check There are problems in package haddock-2.4.2: import-dirs: c:/builds/slave/x86-win-stable/build/ghc-6.10.2\haddock-2.4.2 doesn't exist or isn't a directory library-dirs: c:/builds/slave/x86-win-stable/build/ghc-6.10.2\haddock-2.4.2 doesn't exist or isn't a directory file Distribution\Haddock.hi is missing file Haddock\DocName.hi is missing file Haddock\Types.hi is missing file Haddock\InterfaceFile.hi is missing file Haddock\Exception.hi is missing file Haddock\Utils.hi is missing file Haddock\GHC\Utils.hi is missing cannot find libHShaddock-2.4.2.a on library path The following packages are broken, either because they have a problem listed above, or because they depend on a broken package. haddock-2.4.2 ----------------------------------------------------------------------------------------------------------------------------------------------------- I am using 6.10.2 on windows XP. Any suggestions on how to rectify this? -raja From aditya.siram at gmail.com Fri Apr 10 22:00:34 2009 From: aditya.siram at gmail.com (aditya siram) Date: Fri Apr 10 21:54:47 2009 Subject: [Haskell-beginners] rts package in an invalid state In-Reply-To: <1336aed20904101855i34a2b544n13571524ad697332@mail.gmail.com> References: <594f78210904101406y6b2999d3ucb132d56d63cb129@mail.gmail.com> <42784f260904101540o9f05e1akf1652dce8c5a5ece@mail.gmail.com> <594f78210904101601m7e7185aeg196cc05998ca135c@mail.gmail.com> <1336aed20904101855i34a2b544n13571524ad697332@mail.gmail.com> Message-ID: <594f78210904101900t1c856301yd1ca9a945b3767ef@mail.gmail.com> I had this problem with the HTTP package. I followed the following steps: 1. Unregister the offending package with 'ghc-pkg unregister ' 2. Download the package from Hackage 3. Manually compile and install the package 4. Check that the package is in the list with 'ghc-pkg list' 5. Rerun 'ghc-pkg check' hth, deech On Fri, Apr 10, 2009 at 8:55 PM, Raja Koduru wrote: > Hi, > Just did ghc-pkg check on my system just out of curiosity. > Even here I am getting the rts package errors. > > But I followed the instructions given at the above url to rectify it. > > To my surprise there is one more such error. It is related to haddock-2.4.2. > > Pasting here the 'ghc-pkg check's dump > ---------------------------------------------------------------------------------------------------------------------------------------------------- > C:\Program Files\Haskell>ghc-pkg check > There are problems in package haddock-2.4.2: > ?import-dirs: c:/builds/slave/x86-win-stable/build/ghc-6.10.2\haddock-2.4.2 > doesn't exist or isn't > a directory > ?library-dirs: > c:/builds/slave/x86-win-stable/build/ghc-6.10.2\haddock-2.4.2 doesn't > exist or isn't > ?a directory > ?file Distribution\Haddock.hi is missing > ?file Haddock\DocName.hi is missing > ?file Haddock\Types.hi is missing > ?file Haddock\InterfaceFile.hi is missing > ?file Haddock\Exception.hi is missing > ?file Haddock\Utils.hi is missing > ?file Haddock\GHC\Utils.hi is missing > ?cannot find libHShaddock-2.4.2.a on library path > > The following packages are broken, either because they have a problem > listed above, or because they depend on a broken package. > haddock-2.4.2 > ----------------------------------------------------------------------------------------------------------------------------------------------------- > > > I am using 6.10.2 on windows XP. > > Any suggestions on how to rectify this? > > -raja > From kscraja at gmail.com Fri Apr 10 22:13:38 2009 From: kscraja at gmail.com (Raja Koduru) Date: Fri Apr 10 22:00:22 2009 Subject: [Haskell-beginners] rts package in an invalid state In-Reply-To: <594f78210904101900t1c856301yd1ca9a945b3767ef@mail.gmail.com> References: <594f78210904101406y6b2999d3ucb132d56d63cb129@mail.gmail.com> <42784f260904101540o9f05e1akf1652dce8c5a5ece@mail.gmail.com> <594f78210904101601m7e7185aeg196cc05998ca135c@mail.gmail.com> <1336aed20904101855i34a2b544n13571524ad697332@mail.gmail.com> <594f78210904101900t1c856301yd1ca9a945b3767ef@mail.gmail.com> Message-ID: <1336aed20904101913q1aed37a0g733e3e2d80fe0a26@mail.gmail.com> Thank you. It worked. Instead of downloading the package from hackage I used "cabal install ". Now I am not getting that error. I believe that using cabal and manual compilation are equivalent when it comes to package installation. Correct me If am wrong. -raja From mpm at alumni.caltech.edu Sat Apr 11 05:02:04 2009 From: mpm at alumni.caltech.edu (Michael Mossey) Date: Sat Apr 11 04:49:05 2009 Subject: [Haskell-beginners] question, chapter 10 Real World Haskell Message-ID: <49E05C8C.30600@alumni.caltech.edu> I'll looking at the parser example, page 242 in Chapter 10 of Real World Haskell, and they are defining a type of monadic parser with the help of an operator they call ==> You can find chapter 10 online. This ebook doesn't have page numbers, but you can find the example I'm looking at in the second called "A more interesting parser", about 40% of the way down: The authors have defined their parser by chaining together functions with ==>. The first function is "getState". What confuses me is: they use getState to "get the state out of the Parser," but a Parser is by definition a function that takes the parse state as its lone argument. I don't understand why they can't drop getState entirely. Maybe it's a simply a way to avoid wrapping the entire function in Parser (...)? Some of this stuff looks "inefficient" to me, but I realize that in a lazy language with an optimizing compiler you can often write long chains of functions (many of which discard their results) and not impede efficiency. Thanks, Mike From quentin.moser at unifr.ch Sat Apr 11 08:01:50 2009 From: quentin.moser at unifr.ch (Quentin Moser) Date: Sat Apr 11 07:47:50 2009 Subject: [Haskell-beginners] question, chapter 10 Real World Haskell In-Reply-To: <49E05C8C.30600@alumni.caltech.edu> References: <49E05C8C.30600@alumni.caltech.edu> Message-ID: <20090411140150.2672ec6a@unifr.ch> On Sat, 11 Apr 2009 02:02:04 -0700 Michael Mossey wrote: > I'll looking at the parser example, page 242 in Chapter 10 of Real > World Haskell, and they are defining a type of monadic parser with > the help of an operator they call ==> > > You can find chapter 10 online. This ebook doesn't have page numbers, > but you can find the example I'm looking at in the second called "A > more interesting parser", about 40% of the way down: > > > > The authors have defined their parser by chaining together functions > with ==>. The first function is "getState". What confuses me is: they > use getState to "get the state out of the Parser," but a Parser is by > definition a function that takes the parse state as its lone > argument. I don't understand why they can't drop getState entirely. > Maybe it's a simply a way to avoid wrapping the entire function in > Parser (...)? > > Some of this stuff looks "inefficient" to me, but I realize that in a > lazy language with an optimizing compiler you can often write long > chains of functions (many of which discard their results) and not > impede efficiency. > > > Thanks, > Mike > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners This is a matter of good coding style (in the sense of modularity, maintanability, etc.). As you've seen it, the authors have first started with a (>>?) function that allows them to combine Maybes, that is to combine functions with a possibility of error. We therefore had the following functions and types: > data Maybe a -- The type of parsing results > (>>?) :: Maybe a -> (a -> Maybe b) -> Maybe b > -- To combine parsing functions > > Nothing :: Maybe a -- To signal an error > Just :: a -> Maybe a -- To return a result without error Code written using this (i.e. parseP5_take2) makes explicit use of the representation of parsing results as Maybe values. When they added implicit state and error messages to the machinery, they had to modify their parsing code by renaming things around. More importantly, the changes affected all their code, even the parts that wouldn't make use of the new functionality. If they had already written a huge body of code that could work perfectly well without reporting errors or accessing state, they'd still have needed to refactor it. Now assume they had, instead, treated the type of parsing results as abstract from the beginning: > newtype Parse a = Parse (Maybe a) > -- The type of parsing results > (===>) :: Parse a -> (a -> Parse b) -> Parse b > p ===> f = case p of > Parse Nothing -> Parse Nothing > Parse (Just a) -> f a > > failure :: Parse a > failure = Parse Nothing > > result :: a -> Parse a > result a = Parse (Just a) Writing their code in terms of Parse, (===>), failure and result rather than Maybe, (>>?), Nothing and Just wouldn't have been any more difficult. But they could then have added implicit state and error messages by simpliy replacing the definitions: > newtype Parse a = Parse (ParseState -> Either String (a, ParseState)) > -- The type of parsing results > (===>) :: Parse a -> (a -> Parse b) -> Parse b > (===>) = ... > > failure = bail "generic error" > result = identity > > -- And the new primitives: > bail :: String -> Parse a > getState :: Parse ParseState > putState :: ParseState -> Parse () Doing so, code that didn't make use of the new functionality wouldn't have needed to be modified _at all_. Code that made use of it would simply have called the new functions bail, getState and putState at appropriate points. Given the magnitude of the change in functionality, this is actually pretty incredible. Now, and to finally answer your question: Besides state and errors, there are a number of other useful facilities that can fit in the framework of a (Parse a) type and a (===>) function as above. Real World Haskell will introduce them in a systematic way starting with Chapter 14 (Monads). As long as our parsing code treats the Parse type as abstract, adding another one of these facilities (like, say, backtracking) will be as straightforward as adding state and error messages was in my example above, and won't require any change in code that doesn't make use of it. If we started explicitly using the fact that (Parse a) is a function on ParseState, things would be different. It is, generally, a matter of good style in all programming paradigms to treat values as abstract as often as possible and only access them through a well-defined interface that isn't dependent on their actual representations. This is even more true in cases like this, when the interface in question conforms to a well-known pattern (in this particular case, it's a Monad) that can accomodate a large number of different capabilities and uses. From mpm at alumni.caltech.edu Sat Apr 11 10:41:50 2009 From: mpm at alumni.caltech.edu (Michael Mossey) Date: Sat Apr 11 10:28:44 2009 Subject: [Haskell-beginners] question, chapter 10 Real World Haskell In-Reply-To: <20090411140150.2672ec6a@unifr.ch> References: <49E05C8C.30600@alumni.caltech.edu> <20090411140150.2672ec6a@unifr.ch> Message-ID: <49E0AC2E.2050002@alumni.caltech.edu> Quentin Moser wrote: > On Sat, 11 Apr 2009 02:02:04 -0700 > Michael Mossey wrote: > > > This is a matter of good coding style (in the sense of modularity, > maintanability, etc.). > > As you've seen it, the authors have first > started with a (>>?) function that allows them to combine Maybes, that > is to combine functions with a possibility of error. ... Thanks for the detailed explanation. I like how you show that the original >>? function, and the method of signaling either an error or a result, could have been written with ==> notation. But, I'm still confused on a point. Let me put it this way. The authors wrote: -- file: ch10/Parse.hs -- import the Word8 type from Data.Word parseByte :: Parse Word8 parseByte = getState ==> \initState -> case L.uncons (string initState) of Nothing -> bail "no more input" Just (byte,remainder) -> putState newState ==> \_ -> identity byte where newState = initState { string = remainder, offset = newOffset } newOffset = offset initState + 1 Why couldn't they have avoided getState by writing parseByte = Parse ( \initState -> case L.unconcs (string initState) of ... ... newOffset = offset initState +1 ) ...because a parser is by definition a function that takes ParseState as its input. I understand you are saying that in future chapters they may introduce new capabilities that fit within this framework, so maybe that's what I'm not seeing. Maybe they will redefine getState (or something equivalent) so that it does more than grab the unchanged state from the Parse. But I'm curious to know if my second implementation works the same as the first, in theory. Thanks From daniel.is.fischer at web.de Sat Apr 11 11:27:11 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Sat Apr 11 11:14:06 2009 Subject: [Haskell-beginners] question, chapter 10 Real World Haskell In-Reply-To: <49E0AC2E.2050002@alumni.caltech.edu> References: <49E05C8C.30600@alumni.caltech.edu> <20090411140150.2672ec6a@unifr.ch> <49E0AC2E.2050002@alumni.caltech.edu> Message-ID: <200904111727.11531.daniel.is.fischer@web.de> Am Samstag 11 April 2009 16:41:50 schrieb Michael Mossey: > Quentin Moser wrote: > > On Sat, 11 Apr 2009 02:02:04 -0700 > > Michael Mossey wrote: > > > > > > This is a matter of good coding style (in the sense of modularity, > > maintanability, etc.). > > > > As you've seen it, the authors have first > > started with a (>>?) function that allows them to combine Maybes, that > > is to combine functions with a possibility of error. > > ... > > Thanks for the detailed explanation. I like how you show that the original > >>? function, and the method of signaling either an error or a result, > could have been written with ==> notation. > > But, I'm still confused on a point. Let me put it this way. The authors > wrote: > > -- file: ch10/Parse.hs > -- import the Word8 type from Data.Word > parseByte :: Parse Word8 > parseByte = > getState ==> \initState -> > case L.uncons (string initState) of > Nothing -> > bail "no more input" > Just (byte,remainder) -> > putState newState ==> \_ -> > identity byte > where newState = initState { string = remainder, > offset = newOffset } > newOffset = offset initState + 1 > > > Why couldn't they have avoided getState by writing > > parseByte = Parse ( > \initState -> > case L.unconcs (string initState) of > ... > ... > newOffset = offset initState +1 > ) > > ...because a parser is by definition a function that takes ParseState as > its input. I understand you are saying that in future chapters they may > introduce new capabilities that fit within this framework, so maybe that's > what I'm not seeing. Maybe they will redefine getState (or something > equivalent) so that it does more than grab the unchanged state from the > Parse. In a real library, the constructor Parse would not be exported, to allow later changing the implementation of the Parse type without breaking user code. So user code like parseByte cannot access the constructor and must use the exported API (getState, putState, identity, bail, ...). > > But I'm curious to know if my second implementation works the same as the > first, in theory. As long as the constructor is accessible, yes. > > Thanks From mpm at alumni.caltech.edu Sat Apr 11 12:37:53 2009 From: mpm at alumni.caltech.edu (Michael Mossey) Date: Sat Apr 11 12:24:54 2009 Subject: [Haskell-beginners] question, chapter 10 Real World Haskell In-Reply-To: <200904111727.11531.daniel.is.fischer@web.de> References: <49E05C8C.30600@alumni.caltech.edu> <20090411140150.2672ec6a@unifr.ch> <49E0AC2E.2050002@alumni.caltech.edu> <200904111727.11531.daniel.is.fischer@web.de> Message-ID: <49E0C761.70707@alumni.caltech.edu> Daniel Fischer wrote: > > In a real library, the constructor Parse would not be exported, to allow later changing > the implementation of the Parse type without breaking user code. > So user code like parseByte cannot access the constructor and must use the exported API > (getState, putState, identity, bail, ...). thanks for the point, I get it. One other question. Later in the chapter they define peekByte as follows: -- file: ch10/Parse.hs peekByte :: Parse (Maybe Word8) peekByte = (fmap fst . L.uncons . string) <$> getState Here they are accessing the 'string' field of the state. So whomever writes this function needs to have the accessor functions. At this point I'm wondering how much state is really getting hidden. Or maybe peekByte would only be written inside the original library. I was just playing around and discovered you can choose to export the accessor functions or not. Let's say we have -------- module Mod where data What = What { acc :: Int64 } -------- now in a separate module we write: ------------------- -- All fine: import Mod x1 = What 3 x2 = What { acc = 3 } x3 = acc x1 --------------- Now we revisit the first module and write module Mod ( What(What) ) where Now, import Mod x1 = What 3 -- Fine x2 = What { acc = 3 } -- Error x3 = acc x1 -- Error So apparently this exports the constructor but not the accessor fields. The item can be constructed in the normal way, but not in record syntax way. Finally module Mod ( What(acc) ) where --> This exports the accessors which can be used to access, but not to construct module Mod (What(..)) where --> export everything So the lesson is, if we are going to allow users to write functions like peekByte, we have to export the accessor functions, but not necessarily any constructors. From quentin.moser at unifr.ch Sat Apr 11 13:04:22 2009 From: quentin.moser at unifr.ch (Quentin Moser) Date: Sat Apr 11 12:50:21 2009 Subject: [Haskell-beginners] question, chapter 10 Real World Haskell In-Reply-To: <49E0C761.70707@alumni.caltech.edu> References: <49E05C8C.30600@alumni.caltech.edu> <20090411140150.2672ec6a@unifr.ch> <49E0AC2E.2050002@alumni.caltech.edu> <200904111727.11531.daniel.is.fischer@web.de> <49E0C761.70707@alumni.caltech.edu> Message-ID: <20090411190422.1ed649f6@unifr.ch> On Sat, 11 Apr 2009 09:37:53 -0700 Michael Mossey wrote: > One other question. Later in the > chapter they define peekByte as follows: > > -- file: ch10/Parse.hs > peekByte :: Parse (Maybe Word8) > peekByte = (fmap fst . L.uncons . string) <$> getState > > Here they are accessing the 'string' field of the state. So whomever > writes this function needs to have the accessor functions. At this > point I'm wondering how much state is really getting hidden. Or maybe > peekByte would only be written inside the original library. Even before worrying about the accessor functions, a parsing library would in the first place not even export getState, putState, or the ParseState type. It would instead provide functions like parseByte and peekByte as primitives from which all complex parsers will be built. From daniel.is.fischer at web.de Sat Apr 11 14:16:00 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Sat Apr 11 14:02:51 2009 Subject: [Haskell-beginners] question, chapter 10 Real World Haskell In-Reply-To: <20090411190422.1ed649f6@unifr.ch> References: <49E05C8C.30600@alumni.caltech.edu> <49E0C761.70707@alumni.caltech.edu> <20090411190422.1ed649f6@unifr.ch> Message-ID: <200904112016.00656.daniel.is.fischer@web.de> Am Samstag 11 April 2009 19:04:22 schrieb Quentin Moser: > On Sat, 11 Apr 2009 09:37:53 -0700 > > Michael Mossey wrote: > > One other question. Later in the > > chapter they define peekByte as follows: > > > > -- file: ch10/Parse.hs > > peekByte :: Parse (Maybe Word8) > > peekByte = (fmap fst . L.uncons . string) <$> getState > > > > Here they are accessing the 'string' field of the state. So whomever > > writes this function needs to have the accessor functions. At this > > point I'm wondering how much state is really getting hidden. Or maybe > > peekByte would only be written inside the original library. The point is not so much hiding the state, but hiding the details of the Parse type. newtype Parse a = Parse { runParse :: ParseState -> Either String (a,ParseState) } is, except for the names, StateT ParseState (Either String) a. What peekByte assumes is that there is an instance MonadState ParseState Parse where... , implicitly at least. peekByte won't break if the implementation of Parse is changed, as long as that is maintained. If you look at the haddock docs for Parsec, you'll see that there the State is exposed while GenParser is only exported as an abstract type, allowing the details to be changed if deemed advantageous. > > Even before worrying about the accessor functions, a parsing library > would in the first place not even export getState, putState, or the > ParseState type. It would instead provide functions like parseByte and > peekByte as primitives from which all complex parsers will be built. Parsec does: getParserState setParserState From mpm at alumni.caltech.edu Sat Apr 11 22:05:34 2009 From: mpm at alumni.caltech.edu (Michael Mossey) Date: Sat Apr 11 21:52:45 2009 Subject: [Haskell-beginners] Thinking about monads Message-ID: <49E14C6E.1060209@alumni.caltech.edu> I'm getting a better grasp on monads, I think. My original problem, I think, was that I was still thinking imperatively. So when I saw this: class Monad m where (>>=) :: m a -> (a -> m b) -> m b I didn't understand the "big deal". I thought, okay so you "do" something with the function (a -> m b) and you "arrive" at m b. Now I realize that chaining a sequence of Monads via that function, a -> m b, means that a is available to any function further down the line, because it is an argument to a series of nested functions. So, doSomething = thing >>= \x -> thing2 >>= \y -> return (x,y) >>= produces a series of nested functions in which all the arguments of earlier functions are available to later functions: x and y are available to "return" because they are arguments of functions further up in the chain. This resembles imperative code in which any variable, once set, is available further down. Any clarifications welcome. -Mike From es at ertes.de Sun Apr 12 05:03:01 2009 From: es at ertes.de (Ertugrul Soeylemez) Date: Sun Apr 12 04:49:17 2009 Subject: [Haskell-beginners] Re: Thinking about monads References: <49E14C6E.1060209@alumni.caltech.edu> Message-ID: <20090412110301.0e754e81@tritium.xx> Michael Mossey wrote: > I'm getting a better grasp on monads, I think. My original problem, I > think, was that I was still thinking imperatively. So when I saw this: > > class Monad m where > > (>>=) :: m a -> (a -> m b) -> m b > > I didn't understand the "big deal". I thought, okay so you "do" something with the > function (a -> m b) and you "arrive" at m b. [...] Think of f being a computation, in which something is missing. It takes this something through a parameter. So f is actually a function, which takes a value and results in a computation. Another intuition: f is a parametric computation. Now if c0 is a computation, then c0 >>= f is another computation built by feeding the result of c0 to f. More graphically you've plugged the result cable of c0 to the input port of f. As a real world example, consider a computation, which prints a value x: print x That x has to come from somewhere, so this should actually be a function of some value x: \x -> print x If that x should come from another computation, then (>>=) comes into play. You can pass the result of one computation to the above one. For example, if x comes from the result of getChar, you can write: getChar >>= \x -> print x or simply: getChar >>= print Now to the less specific case. Look at the type of (>>=): (>>=) :: m a -> (a -> m b) -> m b The left parameter of (>>=) is the source computation, which results in something of type a. The right parameter is a parametric computation, which results in something of type b, but depends on something of type a. The result of (>>=) is a computation constructed by feeding the result of the left computation as the parameter to the right computation. I hope, this helped. Greets, Ertugrul. -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://blog.ertes.de/ From mpm at alumni.caltech.edu Sun Apr 12 17:02:40 2009 From: mpm at alumni.caltech.edu (Michael Mossey) Date: Sun Apr 12 16:49:40 2009 Subject: [Haskell-beginners] Re: Thinking about monads In-Reply-To: <20090412110301.0e754e81@tritium.xx> References: <49E14C6E.1060209@alumni.caltech.edu> <20090412110301.0e754e81@tritium.xx> Message-ID: <49E256F0.1020209@alumni.caltech.edu> Ertugrul Soeylemez wrote: > Michael Mossey wrote: > >> I'm getting a better grasp on monads, I think. My original problem, I >> think, was that I was still thinking imperatively. So when I saw this: >> >> class Monad m where >> >> (>>=) :: m a -> (a -> m b) -> m b >> >> I didn't understand the "big deal". I thought, okay so you "do" something with the >> function (a -> m b) and you "arrive" at m b. [...] > > Think of f being a computation, in which something is missing. It takes > this something through a parameter. So f is actually a function, which > takes a value and results in a computation. Another intuition: f is a > parametric computation. Now if c0 is a computation, then > > c0 >>= f > > is another computation built by feeding the result of c0 to f. More > graphically you've plugged the result cable of c0 to the input port of > f. > > As a real world example, consider a computation, which prints a value x: > > print x > > That x has to come from somewhere, so this should actually be a function > of some value x: > > \x -> print x > > If that x should come from another computation, then (>>=) comes into > play. You can pass the result of one computation to the above one. For > example, if x comes from the result of getChar, you can write: > > getChar >>= \x -> print x > > or simply: > > getChar >>= print > Well, here are my thoughts. I know what you write is the way monads are introduced in most of the texts I've seen, but to the eyes of an imperative programmer, nothing "special" is going on. Let's give an example (but replace getChar by something deterministic). When I see thing1 >>= thing2 I think to myself, this is basically the same as: (Example A) f input = result' where result = thing1 input result' = thing2 result But it's not the same, because certain problems arise. What's special about monads is the way they are used and the particular problem they are trying to solve. For example, here are some problems we need to solve: (1) how do you pass state from one function to the next in the most elegant way (avoiding the need to make complicated data types and having the ability to hide implementation details) (2) how do you deal with errors? how do you "return early" from a set of computations that have hit a wall? I confess I have not read any chapters on monads themselves, but I have finished Chapter 10 of Real World Haskell, which is mostly about motivating monads and implementing something very close to them. They use an operator they call ==>, which is nearly identical to >>=. I see one answer to (1). Something like (Example B) f input = thing1 input >>= \result -> thing2 result >>= \result' -> return (result, result') separates the idea of the state we passing "down the chain" from the results we get. I'll rewrite example (A) above, to be more explicit about what we are trying to do: (Example C) f state = (result, result') where (result, state') = thing1 state (result', state'') = thing2 result state' In example (B), the results are naturally available because they are arguments to functions, and all functions further down the chain are nested within them. Now about problem (2)? The way the >>= operator is defined, it allows "short-circuiting" any remaining functions after we get a bad result. If the state is Maybe or Either, we can define >>= such that a result of Nothing or Left causes all remaining functions to be skipped. We could do this without monads, but it would look very ugly. As a beginner, I'm not trying to lecture anyone, but putting down my thoughts so I can get feedback. I feel there's no way to "understand" monads without understanding the motivation of the problem we are trying to solve, or without seeing specific implementations. Chapter 10 of Real World Haskell provides a lot of motivation by showing early awkward attempts to solve these problems. Regards, Mike From es at ertes.de Sun Apr 12 22:33:19 2009 From: es at ertes.de (Ertugrul Soeylemez) Date: Sun Apr 12 22:19:33 2009 Subject: [Haskell-beginners] Re: Thinking about monads References: <49E14C6E.1060209@alumni.caltech.edu> <20090412110301.0e754e81@tritium.xx> <49E256F0.1020209@alumni.caltech.edu> Message-ID: <20090413043319.206c7320@tritium.xx> Hello Michael, you're basically trying to give monads a better name. Don't forget that they are an abstract structure, which means that trying to find intuitions or motivations is the same as trying to find real world examples. Monads are not a way to pass the result of some function to another function. We've got function composition for that. Short-circuiting is a feature of particular monads like Maybe, and as you said, you could well do without them. In Haskell, monads are an abstract combinator class, which brings you mainly two advantages: Generalization of functionality and impure operations encapsulated in pure objects. Those objects are the monadic values, which can be interpreted in a number of ways. I like to interpret them as computations, and this is probably the most common interpretation. Have a look at this: x :: Maybe Integer x = Just 3 As you already know, Maybe is a monad. Just 3 is not a value right away. It is a computation, which results in 3. The result of computations may have a certain structure. Maybe allows lack of a result (the Nothing computation), which adds structure to the result. The list type is also a monad. It adds structure in that it allows arbitrarily many results. Monads also allow you to combine computations (pass the result of one computation to another) in a structure-specific manner. In the Maybe monad, this is the short-circuiting you mentioned, if there is no result. In the list monad, each of the results is passed and all individual results are collected in a larger result list (non-determinism). The big feature is that you can write code, which disregards this structure. This is what I referred to as generalization of functionality. Have a look at the sequence function from Control.Monad: sequence :: [m a] -> m [a] Its type already suggests, what it does. It takes a list of computations and gives a computation, which results in the list of the corresponding results. Example: sequence [Just 3, Just 4, Just 5] = Just [3, 4, 5] sequence [[1,2], [3,4,5]] = [[1,3], [1,4], [1,5], [2,3], [2,4], [2,5]] To understand the second example, view the list monad as a way to encode non-determinism. I've written more about this in section 11 of my monads tutorial [1]. As said, the big advantage here is that you can write the sequence function in a way, which completely disregards the underlying structure implemented through the actual monad, such that you don't need to rewrite it for each monad: sequence [] = return [] sequence (c:cs) = c >>= \r -> sequence cs >>= \rs -> return (r:rs) or by using the mapM function: sequence = mapM id So Haskell monads help you to generalize functionality in the same way as group theory and category theory help you to generalize proofs. I hope, this helps. Greets, Ertugrul. [1] http://ertes.de/articles/monads.html#section-11 Michael Mossey wrote: > > > Ertugrul Soeylemez wrote: > > Michael Mossey wrote: > > > >> I'm getting a better grasp on monads, I think. My original problem, I > >> think, was that I was still thinking imperatively. So when I saw this: > >> > >> class Monad m where > >> > >> (>>=) :: m a -> (a -> m b) -> m b > >> > >> I didn't understand the "big deal". I thought, okay so you "do" something with the > >> function (a -> m b) and you "arrive" at m b. [...] > > > > Think of f being a computation, in which something is missing. It takes > > this something through a parameter. So f is actually a function, which > > takes a value and results in a computation. Another intuition: f is a > > parametric computation. Now if c0 is a computation, then > > > > c0 >>= f > > > > is another computation built by feeding the result of c0 to f. More > > graphically you've plugged the result cable of c0 to the input port of > > f. > > > > As a real world example, consider a computation, which prints a value x: > > > > print x > > > > That x has to come from somewhere, so this should actually be a function > > of some value x: > > > > \x -> print x > > > > If that x should come from another computation, then (>>=) comes into > > play. You can pass the result of one computation to the above one. For > > example, if x comes from the result of getChar, you can write: > > > > getChar >>= \x -> print x > > > > or simply: > > > > getChar >>= print > > > > Well, here are my thoughts. I know what you write is the way monads are introduced in > most of the texts I've seen, but to the eyes of an imperative programmer, nothing > "special" is going on. Let's give an example (but replace getChar by something > deterministic). When I see > > thing1 >>= thing2 > > I think to myself, this is basically the same as: > > (Example A) > f input = result' > where result = thing1 input > result' = thing2 result > > But it's not the same, because certain problems arise. What's special about monads is > the way they are used and the particular problem they are trying to solve. For > example, here are some problems we need to solve: > > (1) how do you pass state from one function to the next in the most elegant way > (avoiding the need to make complicated data types and having the ability to hide > implementation details) > > (2) how do you deal with errors? how do you "return early" from a set of computations > that have hit a wall? > > I confess I have not read any chapters on monads themselves, but I have finished > Chapter 10 of Real World Haskell, which is mostly about motivating monads and > implementing something very close to them. They use an operator they call ==>, which > is nearly identical to >>=. > > I see one answer to (1). Something like > > (Example B) > f input = > thing1 input >>= \result -> > thing2 result >>= \result' -> > return (result, result') > > separates the idea of the state we passing "down the chain" from the results we get. > I'll rewrite example (A) above, to be more explicit about what we are trying to do: > > (Example C) > f state = (result, result') > where (result, state') = thing1 state > (result', state'') = thing2 result state' > > > In example (B), the results are naturally available because they are arguments to > functions, and all functions further down the chain are nested within them. > > Now about problem (2)? The way the >>= operator is defined, it allows > "short-circuiting" any remaining functions after we get a bad result. If the state is > Maybe or Either, we can define >>= such that a result of Nothing or Left causes all > remaining functions to be skipped. We could do this without monads, but it would look > very ugly. > > As a beginner, I'm not trying to lecture anyone, but putting down my thoughts so I > can get feedback. I feel there's no way to "understand" monads without understanding > the motivation of the problem we are trying to solve, or without seeing specific > implementations. Chapter 10 of Real World Haskell provides a lot of motivation by > showing early awkward attempts to solve these problems. > > Regards, > Mike -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://blog.ertes.de/ From kaushalkp at gmail.com Sat Apr 11 08:16:47 2009 From: kaushalkp at gmail.com (kaushal Pathak) Date: Sun Apr 12 22:44:02 2009 Subject: [Haskell-beginners] Need Help Message-ID: <6d9efa350904110516u6d6447cckdfa20c8edf1f85a5@mail.gmail.com> Hi There, Here is a very simple haskell program I have written to find whether a number is prime or not, which doesn't give me any compilation error but gives following run-time error : Any help would help me move ahead, I know that the type concepts is what I am lacking, anly pointer to simple/good article/paper would definitely help. Lots of thannx jut even to look at the mail :-) Regards Kaushal *Run Time Error :* kaushal > isPrime1 171 :1:0: Ambiguous type variable `t' in the constraints: `Integral t' arising from a use of `isPrime1' at :1:0-11 `Floating t' arising from a use of `isPrime1' at :1:0-11 `RealFrac t' arising from a use of `isPrime1' at :1:0-11 Probable fix: add a type signature that fixes these type variable(s) kaushal > *Program :* isPrime1 x = let canDivide num 0 = 0 canDivide num 1 = 0 canDivide num divisor = if ((mod num divisor) == 0) then 1 else canDivide num (divisor - 1) in if ( x == 1 ) then putStrLn("1 is Neither prime nor composite!!!") else if ((canDivide x first_div) == 1) then putStrLn(show(x) ++ " is not a Prime Number!!!") else putStrLn(show(x) ++ " is a Prime Number!!!") where first_div :: Integral a => a ; first_div = round (sqrt x) -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090411/f855590c/attachment.htm From michael at snoyman.com Sun Apr 12 23:29:05 2009 From: michael at snoyman.com (Michael Snoyman) Date: Sun Apr 12 23:15:41 2009 Subject: [Haskell-beginners] Need Help In-Reply-To: <6d9efa350904110516u6d6447cckdfa20c8edf1f85a5@mail.gmail.com> References: <6d9efa350904110516u6d6447cckdfa20c8edf1f85a5@mail.gmail.com> Message-ID: <29bf512f0904122029n32e7c034j891c4dacdfbf9835@mail.gmail.com> On Sat, Apr 11, 2009 at 3:16 PM, kaushal Pathak wrote: > > first_div :: Integral a => a ; first_div = round (sqrt x) > Should in fact be first_div :: Integral a => a ; first_div = round (sqrt $ fromIntegral x) Basically, sqrt has the type signature sqrt :: (Floating a) => a -> a, meaning it only works on things like doubles. The rest of your code only works on integral types. Your code compiles just fine because, in theory, you could have a data structure which in an instance of both Integral and Floating, but the argument you provide is probably just a regular old Int or something like that (I can't be certain, as you have not provided the code that calls isPrime1). Let me know if you'd like further clarification. Michael -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090413/39540c00/attachment.htm From rk at trie.org Sun Apr 12 23:45:33 2009 From: rk at trie.org (Rahul Kapoor) Date: Sun Apr 12 23:32:07 2009 Subject: [Haskell-beginners] Need Help In-Reply-To: <6d9efa350904110516u6d6447cckdfa20c8edf1f85a5@mail.gmail.com> References: <6d9efa350904110516u6d6447cckdfa20c8edf1f85a5@mail.gmail.com> Message-ID: > ?Here is a very simple haskell program I have written to find whether a > number is prime or not, which doesn't give me any compilation error but > gives following run-time error : > The type of isPrime1 function you have defined is inferred to be isPrime1 :: (Integral a, RealFrac a, Floating a) => a -> IO () You can check this quickly using :t isPrime1 in GHCI. When you try to run isPrime1 in GHCI you get a compile error since the argument isPrime1 is an integer which does not satisfy the three constraints (Integral, RealFrac and Floating). You probably wanted to define isPrime1 to have the type (Integer a) => a -> IO () Cheers, Rahul www.artquiver.com What kind of art do you like? From daniel.is.fischer at web.de Mon Apr 13 00:01:26 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Sun Apr 12 23:48:12 2009 Subject: [Haskell-beginners] Need Help In-Reply-To: <6d9efa350904110516u6d6447cckdfa20c8edf1f85a5@mail.gmail.com> References: <6d9efa350904110516u6d6447cckdfa20c8edf1f85a5@mail.gmail.com> Message-ID: <200904130601.26529.daniel.is.fischer@web.de> Am Samstag 11 April 2009 14:16:47 schrieb kaushal Pathak: > Hi There, > Here is a very simple haskell program I have written to find whether a > number is prime or not, which doesn't give me any compilation error but > gives following run-time error : > > Any help would help me move ahead, I know that the type concepts is what I > am lacking, anly pointer to simple/good article/paper would definitely > help. > > Lots of thannx jut even to look at the mail :-) > > Regards > Kaushal > > *Run Time Error :* > > kaushal > isPrime1 171 > > :1:0: > Ambiguous type variable `t' in the constraints: > `Integral t' > arising from a use of `isPrime1' at :1:0-11 > `Floating t' > arising from a use of `isPrime1' at :1:0-11 > `RealFrac t' > arising from a use of `isPrime1' at :1:0-11 > Probable fix: add a type signature that fixes these type variable(s) > kaushal > > > *Program :* > > isPrime1 x = > let canDivide num 0 = 0 > canDivide num 1 = 0 > canDivide num divisor = if ((mod num divisor) == 0) then 1 > else canDivide num (divisor - 1) > in > if ( x == 1 ) > then putStrLn("1 is Neither prime nor composite!!!") > else if ((canDivide x first_div) == 1) > then putStrLn(show(x) ++ " is not a Prime Number!!!") > else putStrLn(show(x) ++ " is a Prime Number!!!") > where > first_div :: Integral a => a ; first_div = round (sqrt x) Make it first_div = round (sqrt $ fromIntegral x) And use Bool for boolean expressions: canDivide num 0 = False canDivide num 1 = False canDivide num divisor = num `mod` divisor == 0 || canDivide num (divisor -1) The error happens because Haskell does no automatic type conversions. In canDivide, you use mod on x, since the type of mod is Prelude> :t mod mod :: (Integral a) => a -> a -> a both arguments of canDivide must belong to the same type which must be an Integral type. The second argument of canDivide is first_div, which you defined as first_div = round (sqrt x) The type of sqrt is Prelude> :t sqrt sqrt :: (Floating a) => a -> a so to call sqrt x, the type of x must belong to the Floating class, the result of sqrt has the same type as its argument. Then you round the result of sqrt, the type of round is Prelude> :t round round :: (RealFrac a, Integral b) => a -> b The argument of round is the result of sqrt, which has the same type as x, which also must belong to the class RealFrac for this to work. So, for your function to work, its argument must have a type belonging to the three classes Integral Floating RealFrac That's perfectly legal, so the code compiles and isPrime1 has the type isPrime1 :: (Integral a, Floating a, RealFrac a) => a -> IO (). And when you type isPrime1 171 at the prompt, ghci doesn't really know what to do, to know that, it must know the exact type of 171 (different types could expose different behaviour and might even lead to different results). Since all classes are standard classes and at least one of them is numeric, ghci tries then to default the type, looking for a type satisfying these constraints in the default list (Integer, Double is the default-default). But there is no type which belongs to all three classes (unless you provide the instances for some type, and it wouldn't really make sense for a type to be Integral as well as Floating), so ghci gives up and reports that it couldn't resolve the type variable. In situations like this, usually the remedy is inserting a few explicit conversion functions. From lych77 at gmail.com Mon Apr 13 04:37:22 2009 From: lych77 at gmail.com (Lych) Date: Mon Apr 13 04:23:57 2009 Subject: [Haskell-beginners] Why does forkIO also create native threads? Message-ID: <3dc20c830904130137s75eaca5bhe515ae9992db6280@mail.gmail.com> I wrote a simple ECHO server like this: ---------------------------------------------------- import Network import System.IO import Control.Concurrent service cs = do ln <- hGetContents cs hPutStr cs ln service cs acceptloop ls = do (cs, host, port) <- accept ls hSetBuffering cs LineBuffering forkIO (service cs) acceptloop ls main = do ls <- listenOn (PortNumber 10061) acceptloop ls ---------------------------------------------------- And tested it with a client that initiates as many parallel connections as possible. The number of connections can just reach to 1000+ on my machine, but I thought it should be more, since forkIO generates lightweight threads. I also examined the number of threads in this process with some tool and it proved there was one native thread per connection. When I replaced the 'forkIO' in the program with 'forkOS', I got an exactly similar result. Have I thought something wrong about forkIO? From bugfact at gmail.com Mon Apr 13 14:35:33 2009 From: bugfact at gmail.com (Peter Verswyvelen) Date: Mon Apr 13 14:22:18 2009 Subject: [Haskell-beginners] Why does forkIO also create native threads? In-Reply-To: <3dc20c830904130137s75eaca5bhe515ae9992db6280@mail.gmail.com> References: <3dc20c830904130137s75eaca5bhe515ae9992db6280@mail.gmail.com> Message-ID: It seems that it's not the forkIO that is creating native threads (using GHC 6.10.1, -O flag) For example, the following code only has 5 threads on my Windows box, while I fork 10 lightweight threads import System.IO import Control.Concurrent import Control.Monad entry :: Char -> IO() entry c = do forever $ putChar c main = do hSetBuffering stdout NoBuffering mapM_ (forkIO . entry) ['0'..'9'] putStrLn "all forked; press ENTER to quit" getLine However, things can get bizarre. When we change the entry function into entry :: Char -> IO() entry c = do putChar c threadDelay maxBound Then on my machine 13 native threads *are* created. This might make sense because its waiting forever, but native threads are also created for the following code: entry :: Char -> IO() entry c = do putChar c forever $ threadDelay 0 This feels like overkill, so it seems threadDelay always forks a new native thread, although this is not documented. We can also get into the dark corners of GHC's lightweight thread scheduling: a thread switch only happens when memory is allocated on the GC head (but this is documented in the API) So the following code will not work, the runtime seems to get stuck in an infinite loop after the first thread is created. entry :: Char -> IO() entry c = do putChar c forever $ return () In artificial cases like this you can use yield entry :: Char -> IO() entry c = do putChar c forever yield On Mon, Apr 13, 2009 at 10:37 AM, Lych wrote: > I wrote a simple ECHO server like this: > ---------------------------------------------------- > import Network > import System.IO > import Control.Concurrent > > service cs = do > ln <- hGetContents cs > hPutStr cs ln > service cs > > > acceptloop ls = do > (cs, host, port) <- accept ls > hSetBuffering cs LineBuffering > forkIO (service cs) > acceptloop ls > > main = do > ls <- listenOn (PortNumber 10061) > acceptloop ls > ---------------------------------------------------- > > And tested it with a client that initiates as many parallel > connections as possible. The number of connections can just reach to > 1000+ on my machine, but I thought it should be more, since forkIO > generates lightweight threads. I also examined the number of threads > in this process with some tool and it proved there was one native > thread per connection. When I replaced the 'forkIO' in the program > with 'forkOS', I got an exactly similar result. Have I thought > something wrong about forkIO? > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090413/12b5b9ba/attachment.htm From mpm at alumni.caltech.edu Mon Apr 13 18:11:42 2009 From: mpm at alumni.caltech.edu (Michael Mossey) Date: Mon Apr 13 17:58:36 2009 Subject: [Haskell-beginners] Re: Thinking about monads In-Reply-To: <20090413043319.206c7320@tritium.xx> References: <49E14C6E.1060209@alumni.caltech.edu> <20090412110301.0e754e81@tritium.xx> <49E256F0.1020209@alumni.caltech.edu> <20090413043319.206c7320@tritium.xx> Message-ID: <49E3B89E.7050400@alumni.caltech.edu> Ertugrul Soeylemez wrote: > Hello Michael, > > you're basically trying to give monads a better name. Don't forget that > they are an abstract structure, which means that trying to find > intuitions or motivations is the same as trying to find real world > examples. > > Monads are not a way to pass the result of some function to another > function. We've got function composition for that. Short-circuiting is > a feature of particular monads like Maybe, and as you said, you could > well do without them. In Haskell, monads are an abstract combinator > class, which brings you mainly two advantages: Generalization of > functionality and impure operations encapsulated in pure objects. > I think I'm starting to get this. Conventional programming languages rarely, if ever, deal with abstractions like the functor or monad. In C++ you would need templates to represent them, and templates are a lot of trouble. OO classes are the main form of abstraction I deal with. > Those objects are the monadic values, which can be interpreted in a > number of ways. I like to interpret them as computations, and this is > probably the most common interpretation. Have a look at this: > > x :: Maybe Integer > x = Just 3 > I know Maybe is both a functor and a monad, and I was thinking: what's the difference? They are both wrappers on types. Then I realized, the difference is: they have different class definitions. class Functor f where fmap :: (a->b) -> f a -> f b (Note how fussy this definition would be in C++. It would be a kind of template, but would probably look a lot more complex and would require lengthy declarations.) class Monad m where a >>= b :: m a -> (a -> m b) -> m b Like functor, there are types m/f, a, and b, but they have a different organization. What about my point that the definition of the >>= operator makes it useful to preserve access to the argument variables of earlier functions in the chain, as follows? nodin = jacy >>= \finnibar -> keary >>= \cody -> return (finnibar, cody) I suppose this is a property of structuring the code this way, and this is not the only way to structure it. So I think what you are saying is that the esseence of the abstraction is in the definition. I think I need more experience to really understand why computer scientists were motivated to make that definition. After many years of OO programming, I immediately analyze a problem in terms of classes and objects... while monads and functors have barely entered my vocabulary. I took a look at your tutorial, and I'll go through it in more depth. Thanks, Mike From aditya.siram at gmail.com Mon Apr 13 19:05:34 2009 From: aditya.siram at gmail.com (aditya siram) Date: Mon Apr 13 18:52:06 2009 Subject: [Haskell-beginners] RWH Ch. 27 TCP Server Example Message-ID: <594f78210904131605tc201bcel1f6052ce9f020440@mail.gmail.com> Hi all, I am trying to understand the TCP Syslog Server example [1] from RWH. Specifically my question is on this piece of code: -- | Process incoming messages procMessages :: MVar () -> Socket -> SockAddr -> IO () procMessages lock connsock clientaddr = do connhdl <- socketToHandle connsock ReadMode hSetBuffering connhdl LineBuffering messages <- hGetContents connhdl mapM_ (handle lock clientaddr) (lines messages) hClose connhdl handle lock clientaddr "syslogtcpserver.hs: client disconnected" How does control stay on "mapM_ (handle lock clientaddr) (lines messages)" ? It would seem that the server would handle one message and immediately close the handle and end - but it doesn't. I'm guessing this has something to do with laziness, but I don't see how to apply it. thanks .. -deech [1] http://book.realworldhaskell.org/read/sockets-and-syslog.html From baguasquirrel at gmail.com Mon Apr 13 19:38:56 2009 From: baguasquirrel at gmail.com (Arthur Chan) Date: Mon Apr 13 19:25:28 2009 Subject: [Haskell-beginners] How would you run a monad within another monad? Message-ID: <74cabd9e0904131638s4ae9c137wc29d58b63d3e2d26@mail.gmail.com> Hey All, Suppose we have this generalized situation: I have some class that does IO with user data, but we want to hide the full IO interface, so we do something like this: class (Monad m) => Doohickey m where getCurrentTime :: m Time olderRecords :: m [String] addRecord :: String -> m () Suppose next that we want to run a monadic value of that type, with some context, inside another monad. For example, we have some file on disk with user data. We want the top level to open the file, and then run a monadic action with the above signature. The username provides the context. Give us a username, and we'll open a file, and then run a monadic value w/ the above signature on the file. e.g. class (Monad m) => TopLevel m where openFileAndRun :: (Doohickey n) => UserName -> n a -> m a In this example, we could have a function that takes an input string s, goes through the old records, and if it sees that s is not present, then it will add it to the records. Suppose then that we want to generalize the interface, so that it could apply equally to a local file, a db, the cloud, whatever. That's why we need the Toplevel monad. We want to separate "what we want to do with the user data" from "how we will store and modify the userdata". Toplevel actions therefore needs to be able to execute Doohickey actions. How would you guys do this? I'm trying to write the signatures but ghc borks on "Ambiguous type variable in the constraints" error. It appears to be caused by the usage of the Doohickey typeclass in the signature of Toplevel, when I actually try to write a monadic value of type Toplevel, that calls a monadic value of type Doohickey. Much thanks for any help! -Arthur -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090413/a041eafc/attachment.htm From jason.dusek at gmail.com Mon Apr 13 22:55:17 2009 From: jason.dusek at gmail.com (Jason Dusek) Date: Mon Apr 13 22:41:58 2009 Subject: [Haskell-beginners] How would you run a monad within another monad? In-Reply-To: <74cabd9e0904131638s4ae9c137wc29d58b63d3e2d26@mail.gmail.com> References: <74cabd9e0904131638s4ae9c137wc29d58b63d3e2d26@mail.gmail.com> Message-ID: <42784f260904131955o2950b509v125b437db426ba0a@mail.gmail.com> Copypasting and loading your code doesn't throw an error. Please, pastebin an example that demonstrates the error. -- Jason Dusek From byorgey at seas.upenn.edu Tue Apr 14 16:42:08 2009 From: byorgey at seas.upenn.edu (Brent Yorgey) Date: Tue Apr 14 16:28:37 2009 Subject: [Haskell-beginners] Re: Thinking about monads In-Reply-To: <49E3B89E.7050400@alumni.caltech.edu> References: <49E14C6E.1060209@alumni.caltech.edu> <20090412110301.0e754e81@tritium.xx> <49E256F0.1020209@alumni.caltech.edu> <20090413043319.206c7320@tritium.xx> <49E3B89E.7050400@alumni.caltech.edu> Message-ID: <20090414204207.GA16671@seas.upenn.edu> On Mon, Apr 13, 2009 at 03:11:42PM -0700, Michael Mossey wrote: > > I know Maybe is both a functor and a monad, and I was thinking: what's the > difference? They are both wrappers on types. Then I realized, the > difference is: they have different class definitions. In fact, every monad should be a functor, but not every functor is a monad. Being a monad is a much stronger condition than being a functor. > > class Functor f where > fmap :: (a->b) -> f a -> f b > > (Note how fussy this definition would be in C++. It would be a kind of > template, but would probably look a lot more complex and would require > lengthy declarations.) > > class Monad m where > a >>= b :: m a -> (a -> m b) -> m b Don't forget return :: a -> m a ! That's the other key method in the Monad class. (There are also >> and 'fail' but those are unimportant---the first is just a specialization of >>=, and fail is a hack). -Brent From baguasquirrel at gmail.com Tue Apr 14 17:05:22 2009 From: baguasquirrel at gmail.com (Arthur Chan) Date: Tue Apr 14 16:52:03 2009 Subject: [Haskell-beginners] How would you run a monad within another monad? In-Reply-To: <42784f260904131955o2950b509v125b437db426ba0a@mail.gmail.com> References: <74cabd9e0904131638s4ae9c137wc29d58b63d3e2d26@mail.gmail.com> <42784f260904131955o2950b509v125b437db426ba0a@mail.gmail.com> Message-ID: <74cabd9e0904141405i1fbadb85u8b87ffb05d61c493@mail.gmail.com> Here's my contrived example that threw the error. If you go into ghci, and do a `:t (foo' "blah" myDoohickey)`, you will get the type signature "IO ()". Doing the same for myOtherDoohickey returns "IO True" So you would think that you'd be able to uncomment the code that makes IO an instance of Toplevel. foo' is a function that allows IO to run monadic values of type Doohickey. But it doesn't work. --- import IO import Control.Monad.Reader class (Monad n) => Doohickey n where putRecord :: String -> n () class (Monad m) => Toplevel m where foo :: (Doohickey n) => FilePath -> n a -> m a newtype IOToplevelT a = IOToplevelT { runIOToplevelT :: ReaderT Handle IO a } deriving (Monad, MonadReader Handle, MonadIO) instance Doohickey IOToplevelT where putRecord = liftIO . putStrLn foo' s k = do f <- liftIO $ openFile s AppendMode runReaderT (runIOToplevelT k) f --instance Toplevel IO where -- foo = foo' myDoohickey = do putRecord "foo" putRecord "bar" myOtherDoohickey = do putRecord "hello" putRecord "world" return True On Mon, Apr 13, 2009 at 7:55 PM, Jason Dusek wrote: > Copypasting and loading your code doesn't throw an error. Please, > pastebin an example that demonstrates the error. > > -- > Jason Dusek > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090414/0c3d6d92/attachment.htm From baguasquirrel at gmail.com Tue Apr 14 17:39:56 2009 From: baguasquirrel at gmail.com (Arthur Chan) Date: Tue Apr 14 17:26:26 2009 Subject: [Haskell-beginners] How would you run a monad within another monad? In-Reply-To: <74cabd9e0904141405i1fbadb85u8b87ffb05d61c493@mail.gmail.com> References: <74cabd9e0904131638s4ae9c137wc29d58b63d3e2d26@mail.gmail.com> <42784f260904131955o2950b509v125b437db426ba0a@mail.gmail.com> <74cabd9e0904141405i1fbadb85u8b87ffb05d61c493@mail.gmail.com> Message-ID: <74cabd9e0904141439u6b146b78n727cc83b0c16a7ca@mail.gmail.com> I seem to have finally solved my own problem, via something I learned from RWH. The solution is to use functional dependencies... The problem was that the compiler needed to know the relationship between Doohickeys and Toplevels, and I couldn't figure out how to tell it that... {-# LANGUAGE GeneralizedNewtypeDeriving, NoMonomorphismRestriction, FunctionalDependencies, MultiParamTypeClasses #-} import IO import Control.Monad.Reader class (Monad n) => Doohickey n where putRecord :: String -> n () class (Monad m, Doohickey n) => Toplevel m n | m -> n where foo :: FilePath -> n a -> m a newtype IODoohickey a = IODoohickey { runIODoohickey :: ReaderT Handle IO a } deriving (Monad, MonadReader Handle, MonadIO) instance Doohickey IODoohickey where putRecord = liftIO . putStrLn instance Toplevel IO IODoohickey where foo s k = do f <- liftIO $ openFile s AppendMode runReaderT (runIODoohickey k) f myDoohickey = do putRecord "foo" putRecord "bar" myOtherDoohickey = do putRecord "hello" putRecord "world" return True On Tue, Apr 14, 2009 at 2:05 PM, Arthur Chan wrote: > Here's my contrived example that threw the error. > > If you go into ghci, and do a `:t (foo' "blah" myDoohickey)`, you will get > the type signature "IO ()". > Doing the same for myOtherDoohickey returns "IO True" > > So you would think that you'd be able to uncomment the code that makes IO > an instance of Toplevel. foo' is a function that allows IO to run monadic > values of type Doohickey. But it doesn't work. > > > --- > > import IO > import Control.Monad.Reader > > > class (Monad n) => Doohickey n where > putRecord :: String -> n () > > class (Monad m) => Toplevel m where > foo :: (Doohickey n) => FilePath -> n a -> m a > > newtype IOToplevelT a = IOToplevelT { runIOToplevelT :: ReaderT Handle IO a > } deriving (Monad, MonadReader Handle, MonadIO) > > instance Doohickey IOToplevelT where > putRecord = liftIO . putStrLn > > foo' s k = do > f <- liftIO $ openFile s AppendMode > runReaderT (runIOToplevelT k) f > > --instance Toplevel IO where > -- foo = foo' > > myDoohickey = do > putRecord "foo" > putRecord "bar" > > myOtherDoohickey = do > putRecord "hello" > putRecord "world" > return True > > > > On Mon, Apr 13, 2009 at 7:55 PM, Jason Dusek wrote: > >> Copypasting and loading your code doesn't throw an error. Please, >> pastebin an example that demonstrates the error. >> >> -- >> Jason Dusek >> > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090414/c3fd4db2/attachment.htm From baguasquirrel at gmail.com Tue Apr 14 17:40:25 2009 From: baguasquirrel at gmail.com (Arthur Chan) Date: Tue Apr 14 17:26:53 2009 Subject: [Haskell-beginners] How would you run a monad within another monad? In-Reply-To: <74cabd9e0904141439u6b146b78n727cc83b0c16a7ca@mail.gmail.com> References: <74cabd9e0904131638s4ae9c137wc29d58b63d3e2d26@mail.gmail.com> <42784f260904131955o2950b509v125b437db426ba0a@mail.gmail.com> <74cabd9e0904141405i1fbadb85u8b87ffb05d61c493@mail.gmail.com> <74cabd9e0904141439u6b146b78n727cc83b0c16a7ca@mail.gmail.com> Message-ID: <74cabd9e0904141440p3ef435c1mba2e7323b196efcf@mail.gmail.com> I wonder how you would do this with type familes... On Tue, Apr 14, 2009 at 2:39 PM, Arthur Chan wrote: > I seem to have finally solved my own problem, via something I learned from > RWH. The solution is to use functional dependencies... > > The problem was that the compiler needed to know the relationship between > Doohickeys and Toplevels, and I couldn't figure out how to tell it that... > > > > {-# LANGUAGE GeneralizedNewtypeDeriving, NoMonomorphismRestriction, > FunctionalDependencies, MultiParamTypeClasses #-} > > import IO > import Control.Monad.Reader > > > class (Monad n) => Doohickey n where > putRecord :: String -> n () > > class (Monad m, Doohickey n) => Toplevel m n | m -> n where > foo :: FilePath -> n a -> m a > > newtype IODoohickey a = IODoohickey { runIODoohickey :: ReaderT Handle IO a > } deriving (Monad, MonadReader Handle, MonadIO) > > instance Doohickey IODoohickey where > putRecord = liftIO . putStrLn > > instance Toplevel IO IODoohickey where > foo s k = do > f <- liftIO $ openFile s AppendMode > runReaderT (runIODoohickey k) f > > > myDoohickey = do > putRecord "foo" > putRecord "bar" > > myOtherDoohickey = do > putRecord "hello" > putRecord "world" > return True > > > > > On Tue, Apr 14, 2009 at 2:05 PM, Arthur Chan wrote: > >> Here's my contrived example that threw the error. >> >> If you go into ghci, and do a `:t (foo' "blah" myDoohickey)`, you will get >> the type signature "IO ()". >> Doing the same for myOtherDoohickey returns "IO True" >> >> So you would think that you'd be able to uncomment the code that makes IO >> an instance of Toplevel. foo' is a function that allows IO to run monadic >> values of type Doohickey. But it doesn't work. >> >> >> --- >> >> import IO >> import Control.Monad.Reader >> >> >> class (Monad n) => Doohickey n where >> putRecord :: String -> n () >> >> class (Monad m) => Toplevel m where >> foo :: (Doohickey n) => FilePath -> n a -> m a >> >> newtype IOToplevelT a = IOToplevelT { runIOToplevelT :: ReaderT Handle IO >> a } deriving (Monad, MonadReader Handle, MonadIO) >> >> instance Doohickey IOToplevelT where >> putRecord = liftIO . putStrLn >> >> foo' s k = do >> f <- liftIO $ openFile s AppendMode >> runReaderT (runIOToplevelT k) f >> >> --instance Toplevel IO where >> -- foo = foo' >> >> myDoohickey = do >> putRecord "foo" >> putRecord "bar" >> >> myOtherDoohickey = do >> putRecord "hello" >> putRecord "world" >> return True >> >> >> >> On Mon, Apr 13, 2009 at 7:55 PM, Jason Dusek wrote: >> >>> Copypasting and loading your code doesn't throw an error. Please, >>> pastebin an example that demonstrates the error. >>> >>> -- >>> Jason Dusek >>> >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090414/e56db9ad/attachment.htm From jason.dusek at gmail.com Tue Apr 14 17:52:29 2009 From: jason.dusek at gmail.com (Jason Dusek) Date: Tue Apr 14 17:38:59 2009 Subject: [Haskell-beginners] How would you run a monad within another monad? In-Reply-To: <74cabd9e0904141439u6b146b78n727cc83b0c16a7ca@mail.gmail.com> References: <74cabd9e0904131638s4ae9c137wc29d58b63d3e2d26@mail.gmail.com> <42784f260904131955o2950b509v125b437db426ba0a@mail.gmail.com> <74cabd9e0904141405i1fbadb85u8b87ffb05d61c493@mail.gmail.com> <74cabd9e0904141439u6b146b78n727cc83b0c16a7ca@mail.gmail.com> Message-ID: <42784f260904141452j28f12881re823d3b6e3a4d1a5@mail.gmail.com> Congratulations. -- Jason Dusek From baguasquirrel at gmail.com Tue Apr 14 18:08:05 2009 From: baguasquirrel at gmail.com (Arthur Chan) Date: Tue Apr 14 17:54:34 2009 Subject: [Haskell-beginners] Re: Thinking about monads (Brent Yorgey) Message-ID: <74cabd9e0904141508w759c12f8o99af20edaf1fdaa2@mail.gmail.com> You know, I was wondering... if Monads are a subset of Functors, and Applicative is a subset of Functors, and Monads are a subset of Applicative... shouldn't it be possible to tack on the definitions that automatically derive Functor and Applicative? Isn't it the case that there is really only one way to define Applicative for a Monad anyway? And isn't there only one way to define fmap for a Monad that makes sense? On Tue, Apr 14, 2009 at 2:39 PM, wrote: > Send Beginners mailing list submissions to > beginners@haskell.org > > To subscribe or unsubscribe via the World Wide Web, visit > http://www.haskell.org/mailman/listinfo/beginners > or, via email, send a message with subject or body 'help' to > beginners-request@haskell.org > > You can reach the person managing the list at > beginners-owner@haskell.org > > When replying, please edit your Subject line so it is more specific > than "Re: Contents of Beginners digest..." > > > Today's Topics: > > 1. Re: Re: Thinking about monads (Brent Yorgey) > 2. Re: How would you run a monad within another monad? > (Arthur Chan) > 3. Re: How would you run a monad within another monad? > (Arthur Chan) > 4. Re: How would you run a monad within another monad? > (Arthur Chan) > 5. Re: How would you run a monad within another monad? > (Jason Dusek) > > > ---------------------------------------------------------------------- > > Message: 1 > Date: Tue, 14 Apr 2009 16:42:08 -0400 > From: Brent Yorgey > Subject: Re: [Haskell-beginners] Re: Thinking about monads > To: beginners@haskell.org > Message-ID: <20090414204207.GA16671@seas.upenn.edu> > Content-Type: text/plain; charset=us-ascii > > On Mon, Apr 13, 2009 at 03:11:42PM -0700, Michael Mossey wrote: > > > > I know Maybe is both a functor and a monad, and I was thinking: what's > the > > difference? They are both wrappers on types. Then I realized, the > > difference is: they have different class definitions. > > In fact, every monad should be a functor, but not every functor is a > monad. Being a monad is a much stronger condition than being a functor. > > > > > class Functor f where > > fmap :: (a->b) -> f a -> f b > > > > (Note how fussy this definition would be in C++. It would be a kind of > > template, but would probably look a lot more complex and would require > > lengthy declarations.) > > > > class Monad m where > > a >>= b :: m a -> (a -> m b) -> m b > > Don't forget return :: a -> m a ! That's the other key method in the > Monad > class. (There are also >> and 'fail' but those are unimportant---the > first is just a specialization of >>=, and fail is a hack). > > -Brent > > > ------------------------------ > > Message: 2 > Date: Tue, 14 Apr 2009 14:05:22 -0700 > From: Arthur Chan > Subject: Re: [Haskell-beginners] How would you run a monad within > another monad? > To: Jason Dusek > Cc: beginners@haskell.org > Message-ID: > <74cabd9e0904141405i1fbadb85u8b87ffb05d61c493@mail.gmail.com> > Content-Type: text/plain; charset="utf-8" > > Here's my contrived example that threw the error. > > If you go into ghci, and do a `:t (foo' "blah" myDoohickey)`, you will get > the type signature "IO ()". > Doing the same for myOtherDoohickey returns "IO True" > > So you would think that you'd be able to uncomment the code that makes IO > an > instance of Toplevel. foo' is a function that allows IO to run monadic > values of type Doohickey. But it doesn't work. > > > --- > > import IO > import Control.Monad.Reader > > > class (Monad n) => Doohickey n where > putRecord :: String -> n () > > class (Monad m) => Toplevel m where > foo :: (Doohickey n) => FilePath -> n a -> m a > > newtype IOToplevelT a = IOToplevelT { runIOToplevelT :: ReaderT Handle IO a > } deriving (Monad, MonadReader Handle, MonadIO) > > instance Doohickey IOToplevelT where > putRecord = liftIO . putStrLn > > foo' s k = do > f <- liftIO $ openFile s AppendMode > runReaderT (runIOToplevelT k) f > > --instance Toplevel IO where > -- foo = foo' > > myDoohickey = do > putRecord "foo" > putRecord "bar" > > myOtherDoohickey = do > putRecord "hello" > putRecord "world" > return True > > > On Mon, Apr 13, 2009 at 7:55 PM, Jason Dusek > wrote: > > > Copypasting and loading your code doesn't throw an error. Please, > > pastebin an example that demonstrates the error. > > > > -- > > Jason Dusek > > > -------------- next part -------------- > An HTML attachment was scrubbed... > URL: > http://www.haskell.org/pipermail/beginners/attachments/20090414/0c3d6d92/attachment-0001.htm > > ------------------------------ > > Message: 3 > Date: Tue, 14 Apr 2009 14:39:56 -0700 > From: Arthur Chan > Subject: Re: [Haskell-beginners] How would you run a monad within > another monad? > To: Jason Dusek > Cc: beginners@haskell.org > Message-ID: > <74cabd9e0904141439u6b146b78n727cc83b0c16a7ca@mail.gmail.com> > Content-Type: text/plain; charset="utf-8" > > I seem to have finally solved my own problem, via something I learned from > RWH. The solution is to use functional dependencies... > > The problem was that the compiler needed to know the relationship between > Doohickeys and Toplevels, and I couldn't figure out how to tell it that... > > > > {-# LANGUAGE GeneralizedNewtypeDeriving, NoMonomorphismRestriction, > FunctionalDependencies, MultiParamTypeClasses #-} > > import IO > import Control.Monad.Reader > > > class (Monad n) => Doohickey n where > putRecord :: String -> n () > > class (Monad m, Doohickey n) => Toplevel m n | m -> n where > foo :: FilePath -> n a -> m a > > newtype IODoohickey a = IODoohickey { runIODoohickey :: ReaderT Handle IO a > } deriving (Monad, MonadReader Handle, MonadIO) > > instance Doohickey IODoohickey where > putRecord = liftIO . putStrLn > > instance Toplevel IO IODoohickey where > foo s k = do > f <- liftIO $ openFile s AppendMode > runReaderT (runIODoohickey k) f > > > myDoohickey = do > putRecord "foo" > putRecord "bar" > > myOtherDoohickey = do > putRecord "hello" > putRecord "world" > return True > > > > > On Tue, Apr 14, 2009 at 2:05 PM, Arthur Chan >wrote: > > > Here's my contrived example that threw the error. > > > > If you go into ghci, and do a `:t (foo' "blah" myDoohickey)`, you will > get > > the type signature "IO ()". > > Doing the same for myOtherDoohickey returns "IO True" > > > > So you would think that you'd be able to uncomment the code that makes IO > > an instance of Toplevel. foo' is a function that allows IO to run > monadic > > values of type Doohickey. But it doesn't work. > > > > > > --- > > > > import IO > > import Control.Monad.Reader > > > > > > class (Monad n) => Doohickey n where > > putRecord :: String -> n () > > > > class (Monad m) => Toplevel m where > > foo :: (Doohickey n) => FilePath -> n a -> m a > > > > newtype IOToplevelT a = IOToplevelT { runIOToplevelT :: ReaderT Handle IO > a > > } deriving (Monad, MonadReader Handle, MonadIO) > > > > instance Doohickey IOToplevelT where > > putRecord = liftIO . putStrLn > > > > foo' s k = do > > f <- liftIO $ openFile s AppendMode > > runReaderT (runIOToplevelT k) f > > > > --instance Toplevel IO where > > -- foo = foo' > > > > myDoohickey = do > > putRecord "foo" > > putRecord "bar" > > > > myOtherDoohickey = do > > putRecord "hello" > > putRecord "world" > > return True > > > > > > > > On Mon, Apr 13, 2009 at 7:55 PM, Jason Dusek >wrote: > > > >> Copypasting and loading your code doesn't throw an error. Please, > >> pastebin an example that demonstrates the error. > >> > >> -- > >> Jason Dusek > >> > > > > > -------------- next part -------------- > An HTML attachment was scrubbed... > URL: > http://www.haskell.org/pipermail/beginners/attachments/20090414/c3fd4db2/attachment-0001.htm > > ------------------------------ > > Message: 4 > Date: Tue, 14 Apr 2009 14:40:25 -0700 > From: Arthur Chan > Subject: Re: [Haskell-beginners] How would you run a monad within > another monad? > To: Jason Dusek > Cc: beginners@haskell.org > Message-ID: > <74cabd9e0904141440p3ef435c1mba2e7323b196efcf@mail.gmail.com> > Content-Type: text/plain; charset="utf-8" > > I wonder how you would do this with type familes... > > > > On Tue, Apr 14, 2009 at 2:39 PM, Arthur Chan >wrote: > > > I seem to have finally solved my own problem, via something I learned > from > > RWH. The solution is to use functional dependencies... > > > > The problem was that the compiler needed to know the relationship between > > Doohickeys and Toplevels, and I couldn't figure out how to tell it > that... > > > > > > > > {-# LANGUAGE GeneralizedNewtypeDeriving, NoMonomorphismRestriction, > > FunctionalDependencies, MultiParamTypeClasses #-} > > > > import IO > > import Control.Monad.Reader > > > > > > class (Monad n) => Doohickey n where > > putRecord :: String -> n () > > > > class (Monad m, Doohickey n) => Toplevel m n | m -> n where > > foo :: FilePath -> n a -> m a > > > > newtype IODoohickey a = IODoohickey { runIODoohickey :: ReaderT Handle IO > a > > } deriving (Monad, MonadReader Handle, MonadIO) > > > > instance Doohickey IODoohickey where > > putRecord = liftIO . putStrLn > > > > instance Toplevel IO IODoohickey where > > foo s k = do > > f <- liftIO $ openFile s AppendMode > > runReaderT (runIODoohickey k) f > > > > > > myDoohickey = do > > putRecord "foo" > > putRecord "bar" > > > > myOtherDoohickey = do > > putRecord "hello" > > putRecord "world" > > return True > > > > > > > > > > On Tue, Apr 14, 2009 at 2:05 PM, Arthur Chan >wrote: > > > >> Here's my contrived example that threw the error. > >> > >> If you go into ghci, and do a `:t (foo' "blah" myDoohickey)`, you will > get > >> the type signature "IO ()". > >> Doing the same for myOtherDoohickey returns "IO True" > >> > >> So you would think that you'd be able to uncomment the code that makes > IO > >> an instance of Toplevel. foo' is a function that allows IO to run > monadic > >> values of type Doohickey. But it doesn't work. > >> > >> > >> --- > >> > >> import IO > >> import Control.Monad.Reader > >> > >> > >> class (Monad n) => Doohickey n where > >> putRecord :: String -> n () > >> > >> class (Monad m) => Toplevel m where > >> foo :: (Doohickey n) => FilePath -> n a -> m a > >> > >> newtype IOToplevelT a = IOToplevelT { runIOToplevelT :: ReaderT Handle > IO > >> a } deriving (Monad, MonadReader Handle, MonadIO) > >> > >> instance Doohickey IOToplevelT where > >> putRecord = liftIO . putStrLn > >> > >> foo' s k = do > >> f <- liftIO $ openFile s AppendMode > >> runReaderT (runIOToplevelT k) f > >> > >> --instance Toplevel IO where > >> -- foo = foo' > >> > >> myDoohickey = do > >> putRecord "foo" > >> putRecord "bar" > >> > >> myOtherDoohickey = do > >> putRecord "hello" > >> putRecord "world" > >> return True > >> > >> > >> > >> On Mon, Apr 13, 2009 at 7:55 PM, Jason Dusek >wrote: > >> > >>> Copypasting and loading your code doesn't throw an error. Please, > >>> pastebin an example that demonstrates the error. > >>> > >>> -- > >>> Jason Dusek > >>> > >> > >> > > > -------------- next part -------------- > An HTML attachment was scrubbed... > URL: > http://www.haskell.org/pipermail/beginners/attachments/20090414/e56db9ad/attachment-0001.htm > > ------------------------------ > > Message: 5 > Date: Tue, 14 Apr 2009 14:52:29 -0700 > From: Jason Dusek > Subject: Re: [Haskell-beginners] How would you run a monad within > another monad? > To: Arthur Chan > Cc: beginners@haskell.org > Message-ID: > <42784f260904141452j28f12881re823d3b6e3a4d1a5@mail.gmail.com> > Content-Type: text/plain; charset=UTF-8 > > Congratulations. > > -- > Jason Dusek > > > ------------------------------ > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > > > End of Beginners Digest, Vol 10, Issue 14 > ***************************************** > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090414/9ace0b1b/attachment-0001.htm From bieffe62 at gmail.com Tue Apr 14 23:41:06 2009 From: bieffe62 at gmail.com (Francesco Bochicchio) Date: Tue Apr 14 23:27:36 2009 Subject: [Haskell-beginners] RWH Ch. 27 TCP Server Example In-Reply-To: <594f78210904131605tc201bcel1f6052ce9f020440@mail.gmail.com> References: <594f78210904131605tc201bcel1f6052ce9f020440@mail.gmail.com> Message-ID: 2009/4/14 aditya siram > Hi all, > I am trying to understand the TCP Syslog Server example [1] from RWH. > Specifically my question is on this piece of code: > -- | Process incoming messages > procMessages :: MVar () -> Socket -> SockAddr -> IO () > procMessages lock connsock clientaddr = > do connhdl <- socketToHandle connsock ReadMode > hSetBuffering connhdl LineBuffering > messages <- hGetContents connhdl > mapM_ (handle lock clientaddr) (lines messages) > hClose connhdl > handle lock clientaddr > "syslogtcpserver.hs: client disconnected" > > How does control stay on "mapM_ (handle lock clientaddr) (lines > messages)" ? It would seem that the server would handle one message > and immediately close the handle and end - but it doesn't. I'm > guessing this has something to do with laziness, but I don't see how > to apply it. I think you are right thinking about laziness. The function hGetContents produces a lazy result (messages), therefore any function that consumes messages could be considered as 'iteratively calling' hGetContents to get new elements of messages ... Laziness is a Very Cool Feature ... when it does not bite you with thunk accumulation problems :-) Ciao ------ FB > > > thanks .. > -deech > > [1] http://book.realworldhaskell.org/read/sockets-and-syslog.html > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090415/66a73b82/attachment.htm From tom.davie at gmail.com Wed Apr 15 02:19:48 2009 From: tom.davie at gmail.com (Thomas Davie) Date: Wed Apr 15 02:06:21 2009 Subject: [Haskell-beginners] Re: Thinking about monads (Brent Yorgey) In-Reply-To: <74cabd9e0904141508w759c12f8o99af20edaf1fdaa2@mail.gmail.com> References: <74cabd9e0904141508w759c12f8o99af20edaf1fdaa2@mail.gmail.com> Message-ID: On 15 Apr 2009, at 00:08, Arthur Chan wrote: > You know, I was wondering... if Monads are a subset of Functors, > and Applicative is a subset of Functors, and Monads are a subset of > Applicative... shouldn't it be possible to tack on the definitions > that automatically derive Functor and Applicative? Isn't it the > case that there is really only one way to define Applicative for a > Monad anyway? And isn't there only one way to define fmap for a > Monad that makes sense? Yes, but at the same time no. Firstly, it's possible that you want an applicative instance that disagrees with your monad one ? not common, and usually ugly, but possible. Secondly, it's often possible to implement the applicative/functor methods in a much more efficient way by dealing with them specifically. In reality, what we want to see is this: class Pointed f where pure :: a -> f a class Functor f where fmap :: (a -> b) -> f a -> f b class (Functor f, Pointed f) => Applicative f where (<*>) :: f (a -> b) -> f a -> f b class (Applicative f) => Monad f where join :: f (f a) -> f a Then we only need to define each behavior in one place, and the tree is neatly seperated out so that if we have something that isn't an Applicative, we can stop implementing after Functor, and if we have something that isn't a Monad, we can stop implementing after Applicative. Bob From byorgey at seas.upenn.edu Thu Apr 16 09:08:53 2009 From: byorgey at seas.upenn.edu (Brent Yorgey) Date: Thu Apr 16 08:55:17 2009 Subject: [Haskell-beginners] Re: Thinking about monads (Brent Yorgey) In-Reply-To: <74cabd9e0904141508w759c12f8o99af20edaf1fdaa2@mail.gmail.com> References: <74cabd9e0904141508w759c12f8o99af20edaf1fdaa2@mail.gmail.com> Message-ID: <20090416130853.GA15065@seas.upenn.edu> On Tue, Apr 14, 2009 at 03:08:05PM -0700, Arthur Chan wrote: > You know, I was wondering... if Monads are a subset of Functors, and > Applicative is a subset of Functors, and Monads are a subset of > Applicative... shouldn't it be possible to tack on the definitions that > automatically derive Functor and Applicative? Isn't it the case that there > is really only one way to define Applicative for a Monad anyway? And isn't > there only one way to define fmap for a Monad that makes sense? Actually, it's already possible to do this, in a way. If you have a Monad, then fmap is liftM, pure is return, and (<*>) is ap. So you already have implementations of Functor and Applicative. In fact, I routinely do this: import Text.ParserCombinators.Parsec instance Applicative (GenParser tok st) where pure = return (<*>) = ap There are also various proposals which would help in automating this sort of process, like "class aliases". But in general, having a nicer class hierarchy as Bob suggests would be much better. -Brent From aditya.siram at gmail.com Thu Apr 16 13:34:59 2009 From: aditya.siram at gmail.com (aditya siram) Date: Thu Apr 16 13:21:23 2009 Subject: [Haskell-beginners] Partial Loading and Debugging with GHCI Message-ID: <594f78210904161034h5746043eu118bd6c5754c73a6@mail.gmail.com> Hi all, I'm curious as to how one would go about debugging the following program: hello :: String hello = "Hello" world :: String world = "World" number :: Int number = 1 helloWorld :: String helloWorld = hello ++ " " ++ world -- This fails! bad :: String bad = hello ++ number Predictably once I load this program into ghci I get the following error: [1 of 1] Compiling Main ( TestCode.hs, interpreted ) TestCode.hs:14:15: Couldn't match expected type `[Char]' against inferred type `Int' In the second argument of `(++)', namely `number' In the expression: hello ++ number In the definition of `bad': bad = hello ++ number Failed, modules loaded: none. At this point what I want to do is to query the output type of the different functions like so: > :t hello but GHCI won't let me because the program hasn't been loaded. I would then have to comment out 'bad', reload the program and query output types to my hearts content. This is fine for a small program, but when I have functions are downriver from 'bad', it gets extremely cumbersome. Is there a way to load a file such that functions that compile stay loaded in the interpreter even if something else fails? Thanks ... -deech -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090416/1f21ec49/attachment.htm From wingedtachikoma at gmail.com Thu Apr 16 16:33:48 2009 From: wingedtachikoma at gmail.com (Sean Bartell) Date: Thu Apr 16 16:20:13 2009 Subject: [Haskell-beginners] Partial Loading and Debugging with GHCI In-Reply-To: <594f78210904161034h5746043eu118bd6c5754c73a6@mail.gmail.com> References: <594f78210904161034h5746043eu118bd6c5754c73a6@mail.gmail.com> Message-ID: You can comment out the definition of bad and add a new one: bad = undefined The file should load properly. Functions that use "bad" will compile too, but if they try to evaluate it an error will be raised. (sorry, forgot to hit "reply to all" the first time) On Thu, Apr 16, 2009 at 1:34 PM, aditya siram wrote: > Hi all, > I'm curious as to how one would go about debugging the following program: > > hello :: String > hello = "Hello" > > world :: String > world = "World" > > number :: Int > number = 1 > > helloWorld :: String > helloWorld = hello ++ " " ++ world > > -- This fails! > bad :: String > bad = hello ++ number > > Predictably once I load this program into ghci I get the following error: > [1 of 1] Compiling Main ( TestCode.hs, interpreted ) > > TestCode.hs:14:15: > Couldn't match expected type `[Char]' against inferred type `Int' > In the second argument of `(++)', namely `number' > In the expression: hello ++ number > In the definition of `bad': bad = hello ++ number > Failed, modules loaded: none. > > At this point what I want to do is to query the output type of the > different functions like so: > > :t hello > but GHCI won't let me because the program hasn't been loaded. > > I would then have to comment out 'bad', reload the program and query output > types to my hearts content. This is fine for a small program, but when I > have functions are downriver from 'bad', it gets extremely cumbersome. Is > there a way to load a file such that functions that compile stay loaded in > the interpreter even if something else fails? > > Thanks ... > -deech > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090416/8e408a7c/attachment-0001.htm From ezyang at MIT.EDU Thu Apr 16 23:34:52 2009 From: ezyang at MIT.EDU (Edward Z. Yang) Date: Thu Apr 16 23:21:16 2009 Subject: [Haskell-beginners] Partial Loading and Debugging with GHCI In-Reply-To: <594f78210904161034h5746043eu118bd6c5754c73a6@mail.gmail.com> References: <594f78210904161034h5746043eu118bd6c5754c73a6@mail.gmail.com> Message-ID: On Thu, 16 Apr 2009, aditya siram wrote: > I'm curious as to how one would go about debugging the following program: Alternatively, instead of trying to find out what the type is (which might something completely unintelligible and unhelpful, due to Haskell's type inferencing), use :: liberally on subexpressions to say "I think the type here should be *blah*"; it will let you zoom in on the compiler-human mismatch much more quickly. I think this is one of the best ways of Haskell debugging. Cheers, Edward From alexander.dunlap at gmail.com Fri Apr 17 01:21:20 2009 From: alexander.dunlap at gmail.com (Alexander Dunlap) Date: Fri Apr 17 01:07:43 2009 Subject: [Haskell-beginners] Partial Loading and Debugging with GHCI In-Reply-To: References: <594f78210904161034h5746043eu118bd6c5754c73a6@mail.gmail.com> Message-ID: <57526e770904162221m5266694dgb5ae43a5cbc0415a@mail.gmail.com> On Thu, Apr 16, 2009 at 8:34 PM, Edward Z. Yang wrote: > On Thu, 16 Apr 2009, aditya siram wrote: >> >> I'm curious as to how one would go about debugging the following program: > > Alternatively, instead of trying to find out what the type is (which > might something completely unintelligible and unhelpful, due to > Haskell's type inferencing), use :: liberally on subexpressions to say > "I think the type here should be *blah*"; it will let you zoom in on the > compiler-human mismatch much more quickly. I think this is one of the > best ways of Haskell debugging. > > Cheers, > Edward > _______________________________________________ I use this technique a lot. By telling the compiler more and more about what you think out to be going on, you can ascertain much more quickly where you disagree with the compiler. Alex From aditya.siram at gmail.com Fri Apr 17 14:11:57 2009 From: aditya.siram at gmail.com (aditya siram) Date: Fri Apr 17 13:58:17 2009 Subject: [Haskell-beginners] Installing Yi With GTK Frontend Message-ID: <594f78210904171111o2fe17322l89d1d7b036cc227@mail.gmail.com> Hi all, I am having issues installing Yi with the GTK frontend. I have GTK2hs installed correctly but when I do 'yi --help' I get: Usage: yi [option...] [file] --self-check run self-checks -f [frontend] --frontend=[frontend] Select frontend, which can be one of: vty -y path --config-file=path Specify a configuration file -V --version Show version information -h --help Show this help --debug Write debug information in a log file -l [num] --line=[num] Start on line number --as=[editor] Start with editor keymap, where editor is one of: emacs, vim, cua --recompile-force Force recompile of custom yi before starting --resume Resume execution of yi from previous state --recompile Recompile custom yi if required then exit --ghc-options=[flags] Flags to pass to GHC Does Yi need a specific version of Gtk2hs? Thanks ... -deech -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090417/b8ce2fe0/attachment.htm From jeff at nokrev.com Sat Apr 18 20:57:31 2009 From: jeff at nokrev.com (Jeff Wheeler) Date: Sat Apr 18 20:43:44 2009 Subject: [Haskell-beginners] Installing Yi With GTK Frontend In-Reply-To: <594f78210904171111o2fe17322l89d1d7b036cc227@mail.gmail.com> References: <594f78210904171111o2fe17322l89d1d7b036cc227@mail.gmail.com> Message-ID: <1240102651.22866.17.camel@ulysses> On Fri, 2009-04-17 at 13:11 -0500, aditya siram wrote: > I am having issues installing Yi with the GTK frontend. I have GTK2hs > installed correctly but when I do 'yi --help' I get: > Does Yi need a specific version of Gtk2hs? It should work on 0.10; I'm not sure about earlier versions. What happens if you try to run `cabal install yi -fpango`? Also, can you try installing the development version? That might provide more insight the problem, as I'm not immediately sure what's wrong. To get the latest version from the darcs repository, try this: $ darcs get http://code.haskell.org/yi/ $ cd yi $ cabal install -fpango And then, try execution via (the -fpango should be the default, but no harm in being verbose) $ yi -fpango Do you get any errors at this point? Jeff Wheeler (Oh, and I apologize to aditya siram; I initially sent this message privately, rather than to the list.) From nathanmholden at gmail.com Sun Apr 19 15:24:15 2009 From: nathanmholden at gmail.com (Nathan Holden) Date: Sun Apr 19 15:10:29 2009 Subject: [Haskell-beginners] Question on Lists Message-ID: <305228b20904191224v1628fcd1n3cdf98b1ee70bdb9@mail.gmail.com> I have been reading Chris Okasaki's PhD thesis on Purely Functional Data Structures (www.cs.cmu.edu/~rwh/theses/*okasaki*.pdf) and it discusses his idea of lazy lists (He uses Standard ML in the paper), and it raised some questions for me. To cut to the chase, my question is this: Say I have list x of length n, and I have a single piece of data y. Does x ++ [y] take more cycles, or the same as if I'd said y:[x] (which would get it on the wrong side?) -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090419/cd6460bc/attachment.htm From alexander.dunlap at gmail.com Sun Apr 19 16:44:03 2009 From: alexander.dunlap at gmail.com (Alexander Dunlap) Date: Sun Apr 19 16:30:21 2009 Subject: [Haskell-beginners] Question on Lists In-Reply-To: <305228b20904191224v1628fcd1n3cdf98b1ee70bdb9@mail.gmail.com> References: <305228b20904191224v1628fcd1n3cdf98b1ee70bdb9@mail.gmail.com> Message-ID: <57526e770904191344w9b6eb4evf621b6d2780aca0f@mail.gmail.com> On Sun, Apr 19, 2009 at 12:24 PM, Nathan Holden wrote: > I have been reading Chris Okasaki's PhD thesis on Purely Functional Data > Structures (www.cs.cmu.edu/~rwh/theses/okasaki.pdf) and it discusses his > idea of lazy lists (He uses Standard ML in the paper), and it raised some > questions for me. > > To cut to the chase, my question is this: > > Say I have list x of length n, and I have a single piece of data y. Does > ? x ++ [y] > take more cycles, or the same as if I'd said y:[x] (which would get it on > the wrong side?) > y:x is O(1), while x ++ [y] is O(n), where n is the number of elements in x. This is because in order to do x ++ [y], you need to traverse all of the elements in x to get to the end, while y:x just puts it onto the front, which is readily available without a traversal. y:[x] is a type error, because that is the same as saying [y,x], but y and x are not the same type so they can't be in a list together. Alex From mpm at alumni.caltech.edu Sun Apr 19 17:30:28 2009 From: mpm at alumni.caltech.edu (Michael Mossey) Date: Sun Apr 19 17:16:58 2009 Subject: [Haskell-beginners] data constructors Message-ID: <49EB97F4.9090906@alumni.caltech.edu> This is probably a side-effect of coming from OO land, but I'm confused about how to organize my data. Let's say I want to model musical information that occurs on a single staff. A staff consists of a list of StaffItem which occurs at specific times. type Time = Double type Staff = [(Time,StaffItem)] A StaffItem can be one of several things. Let's say it can be a "chord" or a "control". I might like to define Chord and Control first: data Chord = Chord { duration :: Double, notes :: [Note] } data Control = DynamicMark Int | TempoMark Int Okay, so now I want to express the idea a StaffItem can be a Chord or a Control. data StaffItem = StaffItemChord Chord | StaffItemControl Control My problem is the awkward need for separately named constructors "StaffItemChord" and "StaffItemControl". Is there a better way? (Is this even right?) Thanks, Mike From mpm at alumni.caltech.edu Sun Apr 19 20:10:42 2009 From: mpm at alumni.caltech.edu (Michael Mossey) Date: Sun Apr 19 19:57:10 2009 Subject: [Haskell-beginners] data constructors In-Reply-To: <49EB97F4.9090906@alumni.caltech.edu> References: <49EB97F4.9090906@alumni.caltech.edu> Message-ID: <49EBBD82.7050300@alumni.caltech.edu> Some additional thoughts: Here is something I'm struggling with. Let's say a piece of music is several staves filled with chords. Staves have names. Each chord in a staff has a time. In informal notation: staff "fred": (time 1.0, chord 1), (time 1.5, chord 2), (time 2.0, chord 3) staff "bob" : (time 1.0, chord 4), (time 2.0, chord 5) When laying out music, I need to find "verticals", which are chords located on different staves which happen to coincide in time. For instance, the above has three verticals: time 1.0: ("fred", chord 1), ("bob", chord 4) time 1.5: ("fred", chord 2) time 2.0: ("fred", chord 3), ("bob", chord 5) I want to write a function that converts the first way of organizing the information into the second. I tried writing types like type Chord = ... type Time = Double type Name = String type TimedChord = (Time,Chord) type Staff = [(Time,Chord)] type NamedStaff = (Name,Staff) type NamedChord = (Name,Chord) type Vertical = [NamedChord] type TimedVertical = (Time,Vertical) The function I want is convert :: [NamedStaff] -> [TimedVertical] As you can imagine, this is a confusing mess, with all these variants on named and timed things. I thought it might help to create functors called Named and Timed, which might help abstracting operations on named and timed things. For example, datatype Named a = Named { namedName :: Name, namedData :: a } instance Functor Named = name a :: Name name a = namedName a x `fmap` f = Named { namedName = namedName x, namedData = f $ namedData x } Any other suggestions? Thanks, Mike From daniel.is.fischer at web.de Sun Apr 19 20:52:48 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Sun Apr 19 20:39:18 2009 Subject: [Haskell-beginners] data constructors In-Reply-To: <49EBBD82.7050300@alumni.caltech.edu> References: <49EB97F4.9090906@alumni.caltech.edu> <49EBBD82.7050300@alumni.caltech.edu> Message-ID: <200904200252.48334.daniel.is.fischer@web.de> Am Montag 20 April 2009 02:10:42 schrieb Michael Mossey: > Some additional thoughts: > > Here is something I'm struggling with. Let's say a piece of music is > several staves filled with chords. Staves have names. Each chord in a staff > has a time. > > In informal notation: > > staff "fred": (time 1.0, chord 1), (time 1.5, chord 2), (time 2.0, chord > 3) staff "bob" : (time 1.0, chord 4), (time 2.0, > chord 5) > > When laying out music, I need to find "verticals", which are chords located > on different staves which happen to coincide in time. For instance, the > above has three verticals: > > time 1.0: ("fred", chord 1), ("bob", chord 4) > time 1.5: ("fred", chord 2) > time 2.0: ("fred", chord 3), ("bob", chord 5) > > I want to write a function that converts the first way of organizing the > information into the second. I tried writing types like > > type Chord = ... > type Time = Double > type Name = String > > type TimedChord = (Time,Chord) > type Staff = [(Time,Chord)] > type NamedStaff = (Name,Staff) > type NamedChord = (Name,Chord) > type Vertical = [NamedChord] > type TimedVertical = (Time,Vertical) > > The function I want is > > convert :: [NamedStaff] -> [TimedVertical] What about import Data.Function (on) import Data.List convert namedStaffs = map timeVertical verticals where nameTimedChords (name,tcs) = [(time,name,chord) | (time, chord) <- tcs] timedNamedChords = sort . foldr merge [] . map nameTimedChords $ namedStaffs fst3 (x,_,_) = x verticals = groupBy ((==) `on` fst3) timedNamedChords timeVertical v@((t,_,_):_) = (t,[(name,chord) | (_,name,chord) <- v]) ? > > As you can imagine, this is a confusing mess, with all these variants on > named and timed things. I thought it might help to create functors called > Named and Timed, which might help abstracting operations on named and timed > things. For example, > > datatype Named a = Named { namedName :: Name, namedData :: a } > > instance Functor Named = > name a :: Name > name a = namedName a > x `fmap` f = Named { namedName = namedName x, namedData = f $ namedData > x } > > Any other suggestions? > Thanks, > Mike > From mpm at alumni.caltech.edu Sun Apr 19 21:25:10 2009 From: mpm at alumni.caltech.edu (Michael Mossey) Date: Sun Apr 19 21:11:37 2009 Subject: [Haskell-beginners] data constructors In-Reply-To: <200904200252.48334.daniel.is.fischer@web.de> References: <49EB97F4.9090906@alumni.caltech.edu> <49EBBD82.7050300@alumni.caltech.edu> <200904200252.48334.daniel.is.fischer@web.de> Message-ID: <49EBCEF6.6010400@alumni.caltech.edu> Daniel Fischer wrote: > > import Data.Function (on) > import Data.List > > convert namedStaffs = map timeVertical verticals > where > nameTimedChords (name,tcs) = [(time,name,chord) | (time, chord) <- tcs] > timedNamedChords = sort . foldr merge [] . map nameTimedChords $ namedStaffs > fst3 (x,_,_) = x > verticals = groupBy ((==) `on` fst3) timedNamedChords > timeVertical v@((t,_,_):_) = (t,[(name,chord) | (_,name,chord) <- v]) > > ? Hi Daniel, Thanks, that is nice and I will learn a lot by studying it. However, a problem. It will be a big benefit to do this lazily because I only need to extract as many verticals as necessary to fit on one page of layout. I realized, as you did, that it would simplify things to care only about NamedTimedChords: type NamedTimedChord = (Name,Time,Chord) Even though there is some redundancy to have every entry carry along its name and time, it is worth it for simplifying things. Here's what I have, to do this lazily and now caring only about NamedTimedChords: toVerticals :: [[NamedTimedChord]] -> [[NamedTimedChord]] toVerticals [] = [] toVerticals staves = firstVertical : toVerticals remainder where time3 (_,time,_) = time firstVertT = minimum $ map (time3 . head) staves usingStaves = [ s | s <- staves, time3 (head s) == firstVertT ] notUsingStaves = [ s | s <- staves, time3 (head s) /= firstVertT ] firstVertical = map head usingStaves remainder = leftOfUsing ++ notUsingStaves leftOfUsing = filter (not . null) (map tail usingStaves) From mpm at alumni.caltech.edu Mon Apr 20 01:24:21 2009 From: mpm at alumni.caltech.edu (Michael Mossey) Date: Mon Apr 20 01:10:46 2009 Subject: [Haskell-beginners] data constructors In-Reply-To: <49EBCEF6.6010400@alumni.caltech.edu> References: <49EB97F4.9090906@alumni.caltech.edu> <49EBBD82.7050300@alumni.caltech.edu> <200904200252.48334.daniel.is.fischer@web.de> <49EBCEF6.6010400@alumni.caltech.edu> Message-ID: <49EC0705.2010900@alumni.caltech.edu> Michael Mossey wrote: > > toVerticals :: [[NamedTimedChord]] -> [[NamedTimedChord]] > toVerticals [] = [] > toVerticals staves = firstVertical : toVerticals remainder > where > time3 (_,time,_) = time > firstVertT = minimum $ map (time3 . head) staves > usingStaves = [ s | s <- staves, time3 (head s) == firstVertT ] > notUsingStaves = [ s | s <- staves, time3 (head s) /= firstVertT ] realized I could use Data.List.partition for this > firstVertical = map head usingStaves > remainder = leftOfUsing ++ notUsingStaves > leftOfUsing = filter (not . null) (map tail usingStaves) > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners From apfelmus at quantentunnel.de Mon Apr 20 03:00:10 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Mon Apr 20 02:46:58 2009 Subject: [Haskell-beginners] Re: data constructors In-Reply-To: <49EBBD82.7050300@alumni.caltech.edu> References: <49EB97F4.9090906@alumni.caltech.edu> <49EBBD82.7050300@alumni.caltech.edu> Message-ID: Michael Mossey wrote: > I want to write a function that converts the first way of organizing the > information into the second. I tried writing types like > > type Chord = ... > type Time = Double > type Name = String > > type TimedChord = (Time,Chord) > type Staff = [(Time,Chord)] > type NamedStaff = (Name,Staff) > type NamedChord = (Name,Chord) > type Vertical = [NamedChord] > type TimedVertical = (Time,Vertical) > > The function I want is > > convert :: [NamedStaff] -> [TimedVertical] > > As you can imagine, this is a confusing mess, with all these variants on > named and timed things. I thought it might help to create functors > called Named and Timed, which might help abstracting operations on named > and timed things. For example, > > datatype Named a = Named { namedName :: Name, namedData :: a } > > instance Functor Named = > name a :: Name > name a = namedName a > x `fmap` f = Named { namedName = namedName x, namedData = f $ > namedData x } > > Any other suggestions? Functors sounds good to me. data Named a = N Name a data Timed a = T Time a instance Functor Named where ... instance Functor Timed where ... convert :: Named [Timed Chord] -> Timed [Named Chord] Bu you can also use plain type synonyms type Named a = (Name,a) type Timed a = (Time,a) and write your own record selectors by hand name :: Named a -> Name name = fst time :: Timed a -> Time time = fst value :: (b,a) -> a value = snd Regards, apfelmus -- http://apfelmus.nfshost.com From apfelmus at quantentunnel.de Mon Apr 20 03:01:01 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Mon Apr 20 02:51:19 2009 Subject: [Haskell-beginners] Re: data constructors In-Reply-To: <49EBBD82.7050300@alumni.caltech.edu> References: <49EB97F4.9090906@alumni.caltech.edu> <49EBBD82.7050300@alumni.caltech.edu> Message-ID: Michael Mossey wrote: > I want to write a function that converts the first way of organizing the > information into the second. I tried writing types like > > type Chord = ... > type Time = Double > type Name = String > > type TimedChord = (Time,Chord) > type Staff = [(Time,Chord)] > type NamedStaff = (Name,Staff) > type NamedChord = (Name,Chord) > type Vertical = [NamedChord] > type TimedVertical = (Time,Vertical) > > The function I want is > > convert :: [NamedStaff] -> [TimedVertical] > > As you can imagine, this is a confusing mess, with all these variants on > named and timed things. I thought it might help to create functors > called Named and Timed, which might help abstracting operations on named > and timed things. For example, > > datatype Named a = Named { namedName :: Name, namedData :: a } > > instance Functor Named = > name a :: Name > name a = namedName a > x `fmap` f = Named { namedName = namedName x, namedData = f $ > namedData x } > > Any other suggestions? Functors sounds good to me. data Named a = N Name a data Timed a = T Time a instance Functor Named where ... instance Functor Timed where ... convert :: Named [Timed Chord] -> Timed [Named Chord] But you can also use plain type synonyms type Named a = (Name,a) type Timed a = (Time,a) and write your own record selectors by hand name :: Named a -> Name name = fst time :: Timed a -> Time time = fst value :: (b,a) -> a value = snd Regards, apfelmus -- http://apfelmus.nfshost.com From apfelmus at quantentunnel.de Mon Apr 20 03:10:35 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Mon Apr 20 02:57:00 2009 Subject: [Haskell-beginners] Re: data constructors In-Reply-To: <49EB97F4.9090906@alumni.caltech.edu> References: <49EB97F4.9090906@alumni.caltech.edu> Message-ID: Michael Mossey wrote: > A StaffItem can be one of several things. Let's say it can be a "chord" > or a "control". I might like to define Chord and Control first: > > data Chord = Chord { duration :: Double, notes :: [Note] } > data Control = DynamicMark Int > | TempoMark Int > > Okay, so now I want to express the idea a StaffItem can be a Chord or a > Control. > > data StaffItem = StaffItemChord Chord > | StaffItemControl Control > > My problem is the awkward need for separately named constructors > "StaffItemChord" and "StaffItemControl". Is there a better way? (Is this > even right?) Why not simply data StaffItem = Chord { duration :: Double, notes :: [Note] } | DynamicMark Int | TempoMark Int Unless you use Control and Chords in isolation, that's entirely fine. It's basically a question of how much type safety you want. If you have a function like chordName :: Chord -> String that should only with proper Chords and not Control messages, giving it the type signature chordName :: StaffItem -> String is less safe; the compiler won't complain if you pass it a Control message. If you want the compiler to complain, then building "type towers" as you did is the way to go. You can use predefined building blocks like Either type StaffLabel = Either Chord Control to build your types. There are a few methods for making things less clumsy available, like for example Wouter Swierstra. Data types ? la carte. http://www.cse.chalmers.se/~wouter/Publications/DataTypesALaCarte.pdf Regards, apfelmus -- http://apfelmus.nfshost.com From noel.kalman at googlemail.com Fri Apr 17 15:58:33 2009 From: noel.kalman at googlemail.com (Kalman Noel) Date: Mon Apr 20 04:40:09 2009 Subject: [Haskell-beginners] Installing Yi With GTK Frontend In-Reply-To: References: Message-ID: <49E8DF69.7020508@googlemail.com> aditya siram schrieb: > I am having issues installing Yi with the GTK frontend. The gtk frontend has been replaced by the pango frontend. It depends on gtk2hs likewise. On installation, pass -fpango to Setup.hs to make sure that the frontend will get installed, or to be told what it doesn't find. Kalman From noel.kalman at googlemail.com Sat Apr 18 03:56:36 2009 From: noel.kalman at googlemail.com (Kalman Noel) Date: Mon Apr 20 04:40:35 2009 Subject: [Haskell-beginners] Partial Loading and Debugging with GHCI In-Reply-To: References: Message-ID: <49E987B4.2010208@googlemail.com> aditya siram schrieb: > I would then have to comment out 'bad', reload the program and query output > types to my hearts content. This is fine for a small program, but when I > have functions are downriver from 'bad', it gets extremely cumbersome. Is > there a way to load a file such that functions that compile stay loaded in > the interpreter even if something else fails? You can identify the offensive functions and write, in your example, bad :: String -- bad = hello ++ number bad = undefined From equaeghe at nospammail.net Mon Apr 20 16:58:09 2009 From: equaeghe at nospammail.net (Erik Quaeghebeur) Date: Mon Apr 20 16:44:21 2009 Subject: [Haskell-beginners] problem cabal install'ing hmatrix Message-ID: $ cabal install hmatrix Resolving dependencies... Configuring hmatrix-0.5.1.1... Preprocessing library hmatrix-0.5.1.1... running dist/build/Numeric/GSL/Special/Internal_hsc_make failed command was: dist/build/Numeric/GSL/Special/Internal_hsc_make >dist/build/Numeric/GSL/Special/Internal.hs cabal: Error: some packages failed to install: hmatrix-0.5.1.1 failed during the building phase. The exception was: exit: ExitFailure 1 What should I do to diagnose/resolve this problem? I'm on Gentoo/amd64 and have also posted this question in the gentoo forums. TIA for any help and pointers, Erik From iand675 at gmail.com Mon Apr 20 19:26:35 2009 From: iand675 at gmail.com (Ian Duncan) Date: Mon Apr 20 19:12:46 2009 Subject: [Haskell-beginners] Parsec 3.0 problems Message-ID: Hello everyone, I have the simple applicative parser combinator: parseLabel = Label <$> (between spaces (char ':') (many1 alphaNum)) This gives me the error: No instance for (Stream s m Char) arising from a use of `spaces' at tree.hs:18:32-37 Possible fix: add an instance declaration for (Stream s m Char) In the first argument of `between', namely `spaces' In the second argument of `(<$>)', namely `(between spaces (char ':') (many1 alphaNum))' In the expression: Label <$> (between spaces (char ':') (many1 alphaNum)) When I test this function in ghci, I have no problems, yet whenever I try to open it in a file it fails. What am I doing wrong? For those who are curious, Label is a data constructor in the following data type: data Loc = Label String | Addr Int deriving Show Thanks! Ian Duncan -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090420/a63cee98/attachment-0001.htm From giulianoxt at gmail.com Mon Apr 20 19:28:44 2009 From: giulianoxt at gmail.com (Giuliano Vilela) Date: Mon Apr 20 19:14:53 2009 Subject: [Haskell-beginners] Design questions for a Pascal interpreter Message-ID: <4086423f0904201628j65e3728pf8c54fc0c3031e22@mail.gmail.com> Hello, I've been doing some research for a upcoming homework project, a Pascal interpreter written in Haskell. As a beginner to the language, I have a few design questions I'd like to share with you. I started playing with Parsec, getting a feel for parsing with monadic combinators. My assumption here is that i'm going to take the source, transform it in an AST (built with normal data constructors present in Haskell), maybe build a symbol table while doing that (using the implicity state in Parsec), do some checking (mainly type checking I think), and the evaluation itself. Here are a few questions I had so far: - Keeping the whole AST in memory for the evalution phase seems overkill. Is there a better way? - The evalution, I think, would be a set of nice pure mutually recursive functions that do some pattern matching on the program AST. I would pass the current stack and heap for those functions to use and modify. Is the State monad a good fit for this task? Wouldn't the code become "too imperative"? - And finally, the big question. Consider the following pascal source: program HelloWorld; begin writeln('Hello World'); end. To evaluate the AST, I would eventually arrive at something like: eval (FunctionCall func_name func_args) = ... Obviously, to evaluate writeln I need to be in the IO monad. Here, my whole scheme went down. Do I really have to mix my own state (stack, heap) within the IO monad along my evaluation functions? PS: I could keep a list of things to print, that I would eventually do after I traversed the whole tree, but that wouldn't be "realistic". Thank you! -- []'s Giuliano Vilela. From ajb at spamcop.net Mon Apr 20 20:14:01 2009 From: ajb at spamcop.net (ajb@spamcop.net) Date: Mon Apr 20 20:00:10 2009 Subject: [Haskell-beginners] Design questions for a Pascal interpreter In-Reply-To: <4086423f0904201628j65e3728pf8c54fc0c3031e22@mail.gmail.com> References: <4086423f0904201628j65e3728pf8c54fc0c3031e22@mail.gmail.com> Message-ID: <20090420201401.gtphm1ea0wckw8k0-nwo@webmail.spamcop.net> G'day all. Quoting Giuliano Vilela : > - Keeping the whole AST in memory for the evalution phase seems > overkill. Is there a better way? In this day and age, it's not considered overkill to keep an entire program in memory in a tree form. Perl 5 does that, for example. However, Pascal is simple enough that it can be translated from within the parser. Quite a few influential Pascal compilers, including the simplest ones such as Pascal-P and Pascal-S, and some not-so-simple ones such as Turbo Pascal, did not even generate an AST, but compiled straight to P-code or assembly code from within the parser. > - The evalution, I think, would be a set of nice pure mutually > recursive functions that do some pattern matching on the program AST. > I would pass the current stack and heap for those functions to use and > modify. Is the State monad a good fit for this task? Wouldn't the code > become "too imperative"? Interpretation of an imperative language is imperative. I wouldn't worry about it. You will probably end up using a few monad transformers, because you need to need at least I/O and a heap, and quite possibly a symbol table as well. > Obviously, to evaluate writeln I need to be in the IO monad. Here, my > whole scheme went down. Do I really have to mix my own state (stack, > heap) within the IO monad along my evaluation functions? You really need to learn about monad transformers. Try this for starters: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.17.268 Good luck, and let us know how you go. Cheers, Andrew Bromage From flippa at flippac.org Mon Apr 20 22:17:50 2009 From: flippa at flippac.org (Philippa Cowderoy) Date: Mon Apr 20 22:04:11 2009 Subject: [Haskell-beginners] Parsec 3.0 problems In-Reply-To: References: Message-ID: <1240280270.9080.5.camel@flippa-eee> On Mon, 2009-04-20 at 18:26 -0500, Ian Duncan wrote: > No instance for (Stream s m Char) > arising from a use of `spaces' at tree.hs:18:32-37 > Possible fix: add an instance declaration for (Stream s m Char) > In the first argument of `between', namely `spaces' > In the second argument of `(<$>)', namely > `(between spaces (char ':') (many1 alphaNum))' > In the expression: > Label <$> (between spaces (char ':') (many1 alphaNum)) > > > When I test this function in ghci, I have no problems, yet whenever I > try to open it in a file it fails. What am I doing wrong? Looks like you're getting bitten by the monomorphism restriction. {-# LANGUAGE NoMonomorphismRestriction #-} at the top of the source file to make it go away. The MR is a real usability problem for Parsec 3, sadly :-( You may find it easier to work with the latest version of Parsec 2, which is still the recommended version for most purposes. -- Philippa Cowderoy From amitava.shee at gmail.com Tue Apr 21 09:27:57 2009 From: amitava.shee at gmail.com (Amitava Shee) Date: Tue Apr 21 09:14:07 2009 Subject: [Haskell-beginners] typeclass error Message-ID: I have the following code -- foo.hs module Foo where class Foo a where bar :: a -> a instance Foo Int where bar i = i + 10 ------------------ It fails to compile withe following error *Foo> bar 10 :1:4: Ambiguous type variable `t' in the constraints: `Num t' arising from the literal `10' at :1:4-5 `Foo t' arising from a use of `bar' at :1:0-5 Probable fix: add a type signature that fixes these type variable(s) *Foo> - Thanks Amitava Shee -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090421/e448181f/attachment.htm From jfredett at gmail.com Tue Apr 21 09:42:15 2009 From: jfredett at gmail.com (Joe Fredette) Date: Tue Apr 21 09:28:44 2009 Subject: [Haskell-beginners] typeclass error In-Reply-To: References: Message-ID: <49EDCD37.7020406@gmail.com> If I'm not mistaken, changing: bar i = i + 10 to bar i = i + 10::Int ought to fix it. The issue is that the compiler is being to general wrt the type of "10", it's inferring that it's just of type (Num a => a) -- the type of all numbers (sortof.) Alternately, you could implement this as: instance Num a => Foo a where bar x = x + 10 which similarly ought to fix it. Do you understand why? Amitava Shee wrote: > I have the following code > > -- foo.hs > module Foo where > > class Foo a where > bar :: a -> a > > instance Foo Int where > bar i = i + 10 > > ------------------ > > It fails to compile withe following error > *Foo> bar 10 > > :1:4: > Ambiguous type variable `t' in the constraints: > `Num t' arising from the literal `10' at :1:4-5 > `Foo t' arising from a use of `bar' at :1:0-5 > Probable fix: add a type signature that fixes these type variable(s) > *Foo> > > - Thanks > Amitava Shee > ------------------------------------------------------------------------ > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -------------- next part -------------- A non-text attachment was scrubbed... Name: jfredett.vcf Type: text/x-vcard Size: 296 bytes Desc: not available Url : http://www.haskell.org/pipermail/beginners/attachments/20090421/be3b36aa/jfredett.vcf From quentin.moser at unifr.ch Tue Apr 21 10:02:55 2009 From: quentin.moser at unifr.ch (Quentin Moser) Date: Tue Apr 21 09:48:03 2009 Subject: [Haskell-beginners] typeclass error In-Reply-To: References: Message-ID: <20090421160255.722a2d1e@unifr.ch> On Tue, 21 Apr 2009 09:27:57 -0400 Amitava Shee wrote: > I have the following code > > -- foo.hs > module Foo where > > class Foo a where > bar :: a -> a > > instance Foo Int where > bar i = i + 10 > > ------------------ > > It fails to compile withe following error > *Foo> bar 10 > > :1:4: > Ambiguous type variable `t' in the constraints: > `Num t' arising from the literal `10' at :1:4-5 > `Foo t' arising from a use of `bar' at :1:0-5 > Probable fix: add a type signature that fixes these type > variable(s) *Foo> > When you type an expression into GHCi, it needs to be able to assign it a monomorphic type (a type without variables) in order to know which "show" to use on it to print it. From the types of bar (Foo a => a -> a) and 10 (Num a => a), GHCi can only deduce that bar 10 should have type ((Foo a, Num a) => a). It's also not smart enough to notice that there's only one type that's an instance of both Foo and Bar, and use it. Your declarations are perfectly fine, but there's not enough information at the call site of bar to pin it down to a particular type. It can be solved simply by adding a type signature there (bar 10 :: Int). Note also that, since numeric code is common and uses a lot of type classes, Haskell has ad-hoc defaulting rules for it: When there's an ambiguity on the type of a variable and at least one of its class constraints is numeric (e.g. Num or Integral), the compiler will try to use a default type. Unfortunately the default Num type is Integer which isn't an instance of Foo, so the defaulting rules don't apply in your case. From amitava.shee at gmail.com Tue Apr 21 11:21:11 2009 From: amitava.shee at gmail.com (Amitava Shee) Date: Tue Apr 21 11:07:21 2009 Subject: [Haskell-beginners] typeclass error In-Reply-To: <49EDCD37.7020406@gmail.com> References: <49EDCD37.7020406@gmail.com> Message-ID: Thank you. I get the following error after making the suggested changes -- foo.hs {-# LANGUAGE FlexibleInstances #-} module Foo where class Foo a where bar :: a -> a -- -- instance Foo Int where -- bar i = i + 10 -- -- instance Foo [Char] where -- bar m = "foo" ++ m -- instance Num a => Foo a where bar x = x + 10 ----- foo.hs:14:0: Constraint is no smaller than the instance head in the constraint: Num a (Use -XUndecidableInstances to permit this) In the instance declaration for `Foo a' Failed, modules loaded: none. Prelude> ...Amitava On Tue, Apr 21, 2009 at 9:42 AM, Joe Fredette wrote: > If I'm not mistaken, changing: > > bar i = i + 10 > > to > > bar i = i + 10::Int > > ought to fix it. > > The issue is that the compiler is being to general wrt the type of "10", > it's inferring that it's just of type (Num a => a) -- the type of all > numbers (sortof.) > > Alternately, you could implement this as: > > instance Num a => Foo a where > bar x = x + 10 > > which similarly ought to fix it. Do you understand why? > > Amitava Shee wrote: > >> I have the following code >> >> -- foo.hs >> module Foo where >> >> class Foo a where >> bar :: a -> a >> instance Foo Int where >> bar i = i + 10 >> ------------------ >> >> It fails to compile withe following error >> *Foo> bar 10 >> >> :1:4: >> Ambiguous type variable `t' in the constraints: >> `Num t' arising from the literal `10' at :1:4-5 >> `Foo t' arising from a use of `bar' at :1:0-5 >> Probable fix: add a type signature that fixes these type variable(s) >> *Foo> >> >> - Thanks >> Amitava Shee >> ------------------------------------------------------------------------ >> >> _______________________________________________ >> Beginners mailing list >> Beginners@haskell.org >> http://www.haskell.org/mailman/listinfo/beginners >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090421/29e865ab/attachment.htm From jfredett at gmail.com Tue Apr 21 12:44:06 2009 From: jfredett at gmail.com (Joe Fredette) Date: Tue Apr 21 12:30:20 2009 Subject: [Haskell-beginners] typeclass error In-Reply-To: References: <49EDCD37.7020406@gmail.com> Message-ID: <49EDF7D6.4030503@gmail.com> Right, I was incorrect, you should use the solution that Quentin gave- to recap it, The basic problem is that GHCi is trying to infer a single type -- called "monomorphic" -- for your more general type. the type of `bar` is `Foo a => a -> a`, when ghci looks at a literal number (like 10) it interprets it as a "default" type of Integer (not int). Since Integer does not instance Foo, then GHCi yells at you. Quentin explained it far better than I, I refer you to his email. /Joe Amitava Shee wrote: > Thank you. > > I get the following error after making the suggested changes > > -- foo.hs > {-# LANGUAGE FlexibleInstances #-} > module Foo where > > class Foo a where > bar :: a -> a > -- > -- instance Foo Int where > -- bar i = i + 10 > -- > -- instance Foo [Char] where > -- bar m = "foo" ++ m > -- > > instance Num a => Foo a where > bar x = x + 10 > > ----- > > foo.hs:14:0: > Constraint is no smaller than the instance head > in the constraint: Num a > (Use -XUndecidableInstances to permit this) > In the instance declaration for `Foo a' > Failed, modules loaded: none. > Prelude> > > ...Amitava > > On Tue, Apr 21, 2009 at 9:42 AM, Joe Fredette > wrote: > > If I'm not mistaken, changing: > > bar i = i + 10 > > to > > bar i = i + 10::Int > > ought to fix it. > > The issue is that the compiler is being to general wrt the type of > "10", it's inferring that it's just of type (Num a => a) -- the > type of all numbers (sortof.) > > Alternately, you could implement this as: > > instance Num a => Foo a where > bar x = x + 10 > > which similarly ought to fix it. Do you understand why? > > Amitava Shee wrote: > > I have the following code > > -- foo.hs > module Foo where > > class Foo a where > bar :: a -> a > instance Foo Int where > bar i = i + 10 > ------------------ > > It fails to compile withe following error > *Foo> bar 10 > > :1:4: > Ambiguous type variable `t' in the constraints: > `Num t' arising from the literal `10' at :1:4-5 > `Foo t' arising from a use of `bar' at :1:0-5 > Probable fix: add a type signature that fixes these type > variable(s) > *Foo> > > - Thanks > Amitava Shee > ------------------------------------------------------------------------ > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > > > -------------- next part -------------- A non-text attachment was scrubbed... Name: jfredett.vcf Type: text/x-vcard Size: 296 bytes Desc: not available Url : http://www.haskell.org/pipermail/beginners/attachments/20090421/b856729c/jfredett-0001.vcf From bugfact at gmail.com Tue Apr 21 17:54:41 2009 From: bugfact at gmail.com (Peter Verswyvelen) Date: Tue Apr 21 17:40:50 2009 Subject: [Haskell-beginners] Design questions for a Pascal interpreter In-Reply-To: <20090420201401.gtphm1ea0wckw8k0-nwo@webmail.spamcop.net> References: <4086423f0904201628j65e3728pf8c54fc0c3031e22@mail.gmail.com> <20090420201401.gtphm1ea0wckw8k0-nwo@webmail.spamcop.net> Message-ID: Maybe you could get come inspiration from the BASIC interpreter written in Haskell: http://hackage.haskell.org/cgi-bin/hackage-scripts/package/vintage-basic On Tue, Apr 21, 2009 at 2:14 AM, wrote: > G'day all. > > Quoting Giuliano Vilela : > > - Keeping the whole AST in memory for the evalution phase seems >> overkill. Is there a better way? >> > > In this day and age, it's not considered overkill to keep an entire > program in memory in a tree form. Perl 5 does that, for example. > > However, Pascal is simple enough that it can be translated from > within the parser. Quite a few influential Pascal compilers, > including the simplest ones such as Pascal-P and Pascal-S, and some > not-so-simple ones such as Turbo Pascal, did not even generate an AST, > but compiled straight to P-code or assembly code from within the parser. > > - The evalution, I think, would be a set of nice pure mutually >> recursive functions that do some pattern matching on the program AST. >> I would pass the current stack and heap for those functions to use and >> modify. Is the State monad a good fit for this task? Wouldn't the code >> become "too imperative"? >> > > Interpretation of an imperative language is imperative. I wouldn't > worry about it. > > You will probably end up using a few monad transformers, because you > need to need at least I/O and a heap, and quite possibly a symbol > table as well. > > Obviously, to evaluate writeln I need to be in the IO monad. Here, my >> whole scheme went down. Do I really have to mix my own state (stack, >> heap) within the IO monad along my evaluation functions? >> > > You really need to learn about monad transformers. Try this for > starters: > > http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.17.268 > > Good luck, and let us know how you go. > > Cheers, > Andrew Bromage > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090421/4bb970c9/attachment.htm From s.clover at gmail.com Tue Apr 21 22:18:49 2009 From: s.clover at gmail.com (Sterling Clover) Date: Tue Apr 21 22:00:16 2009 Subject: [Haskell-beginners] Re: data constructors In-Reply-To: References: <49EB97F4.9090906@alumni.caltech.edu> <49EBBD82.7050300@alumni.caltech.edu> Message-ID: Maybe just bikeshedding here (and on -beginners, no less), but this seems like a job for Data.Traversable.sequence? sequence :: Monad m => t (m a) -> m (t a) Cheers, S. On Apr 20, 2009, at 3:00 AM, Heinrich Apfelmus wrote: > > Functors sounds good to me. > > data Named a = N Name a > data Timed a = T Time a > > instance Functor Named where ... > instance Functor Timed where ... > > convert :: Named [Timed Chord] -> Timed [Named Chord] > > > Bu you can also use plain type synonyms > > type Named a = (Name,a) > type Timed a = (Time,a) > > and write your own record selectors by hand > > name :: Named a -> Name > name = fst > > time :: Timed a -> Time > time = fst > > value :: (b,a) -> a > value = snd > > > > Regards, > apfelmus > > -- > http://apfelmus.nfshost.com > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners From apfelmus at quantentunnel.de Wed Apr 22 04:07:17 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Wed Apr 22 03:53:33 2009 Subject: [Haskell-beginners] Re: problem cabal install'ing hmatrix In-Reply-To: References: Message-ID: Erik Quaeghebeur wrote: > $ cabal install hmatrix > Resolving dependencies... > Configuring hmatrix-0.5.1.1... > Preprocessing library hmatrix-0.5.1.1... > running dist/build/Numeric/GSL/Special/Internal_hsc_make failed > command was: dist/build/Numeric/GSL/Special/Internal_hsc_make >> dist/build/Numeric/GSL/Special/Internal.hs > cabal: Error: some packages failed to install: > hmatrix-0.5.1.1 failed during the building phase. The exception was: > exit: ExitFailure 1 > > What should I do to diagnose/resolve this problem? > I'm on Gentoo/amd64 and have also posted this question in the gentoo > forums. Try cabal install hmatrix --verbose to get a more detailed failure report. On Mac/PPC, the trickiest part for me was to meet the dependencies on C libraries, and there was some x86 assembly instruction lurking around. Otherwise, no idea. You might want to try the haskell-cafe@haskell.org or libraries@haskell.org mailing lists. Regards, apfelmus -- http://apfelmus.nfshost.com From apfelmus at quantentunnel.de Wed Apr 22 04:21:24 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Wed Apr 22 04:07:39 2009 Subject: [Haskell-beginners] Re: data constructors In-Reply-To: References: <49EB97F4.9090906@alumni.caltech.edu> <49EBBD82.7050300@alumni.caltech.edu> Message-ID: Sterling Clover wrote: > Maybe just bikeshedding here (and on -beginners, no less), but this > seems like a job for Data.Traversable.sequence? > > sequence :: Monad m => t (m a) -> m (t a) > > Cheers, > S. > > Heinrich Apfelmus wrote: >> >> convert :: Named [Timed Chord] -> Timed [Named Chord] >> Great idea! My type signature is wrong, it should actually read convert :: [Named [Timed Chord]] -> [Timed [Named Chord]] I'm not sure whether sequence applies directly, type EventList a = [Timed a] is not a monad. It's not quite an applicative functor either, because in (<*>) :: EventList (a -> b) -> EventList a -> EventList b it's not clear what should happen to events from the left and right list that are not simultaneous. This needs further thought. Regards, apfelmus -- http://apfelmus.nfshost.com From daniel.carrera at theingots.org Wed Apr 22 06:21:14 2009 From: daniel.carrera at theingots.org (Daniel Carrera) Date: Wed Apr 22 06:07:21 2009 Subject: [Haskell-beginners] WWAAA... I hate monads Message-ID: <49EEEF9A.10307@theingots.org> I hate monads. I love 90% of Haskell. The functional stuff is beautiful, easy to understand, crystal clear, elegant, etc. But I'm having a mighty hard time getting my head around monads. Consider the following explanation of a monad: "A monad is represented as a type constructor (call it m), a function that builds values of that type (a -> m a), and a function that combines values of that type with computations that produce values of that type to produce a new computation for values of that type". 1) I know what a type is, but not a "type constructor". I don't normally think of an Int or even a complex type as being "constructed" except in the sense of OOP which I know is not what the author means. 2) Just *read* the paragraph... "a type constructor, a function that builds value of that type, and a function that combines values of that type with computations that produce values of that type to produce a computation of values of that type" Ugh.... Can anyone recommend a simple and clear explanation of monads? You can assume that I know basic math and basic Haskell syntax. So, for example, "a -> b" is much more clear than "a function that takes input of one type and has an output of a different type". Any help would be appreciated. Daniel. From colin at colina.demon.co.uk Wed Apr 22 06:26:06 2009 From: colin at colina.demon.co.uk (Colin Paul Adams) Date: Wed Apr 22 06:12:13 2009 Subject: [Haskell-beginners] WWAAA... I hate monads In-Reply-To: <49EEEF9A.10307@theingots.org> (Daniel Carrera's message of "Wed\, 22 Apr 2009 12\:21\:14 +0200") References: <49EEEF9A.10307@theingots.org> Message-ID: >>>>> "Daniel" == Daniel Carrera writes: Daniel> Can anyone recommend a simple and clear explanation of Daniel> monads? You can assume that I know basic math and basic Daniel> Haskell syntax. So, for example, "a -> b" is much more Daniel> clear than "a function that takes input of one type and Daniel> has an output of a different type". This is excellent: http://ertes.de/articles/monads.html -- Colin Adams Preston Lancashire From daniel.carrera at theingots.org Wed Apr 22 06:34:04 2009 From: daniel.carrera at theingots.org (Daniel Carrera) Date: Wed Apr 22 06:20:13 2009 Subject: [Haskell-beginners] WWAAA... I hate monads In-Reply-To: References: <49EEEF9A.10307@theingots.org> Message-ID: <49EEF29C.8010400@theingots.org> Colin Paul Adams wrote: > This is excellent: > > http://ertes.de/articles/monads.html Thanks! I'll start reading that page immediately. Cheers, Daniel. From wagner.andrew at gmail.com Wed Apr 22 06:55:49 2009 From: wagner.andrew at gmail.com (Andrew Wagner) Date: Wed Apr 22 06:41:56 2009 Subject: [Haskell-beginners] WWAAA... I hate monads In-Reply-To: <49EEEF9A.10307@theingots.org> References: <49EEEF9A.10307@theingots.org> Message-ID: Here's a clearer description:class Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b Instances of Monad must satisfy the following laws: return a >>= k == k a m >>= return == m m >>= (k >>= h) == (m >>= k) >>= h Much more clear and concise, don't you think? On Wed, Apr 22, 2009 at 6:21 AM, Daniel Carrera < daniel.carrera@theingots.org> wrote: > I hate monads. > > I love 90% of Haskell. The functional stuff is beautiful, easy to > understand, crystal clear, elegant, etc. But I'm having a mighty hard time > getting my head around monads. Consider the following explanation of a > monad: > > "A monad is represented as a type constructor (call it m), a function that > builds values of that type (a -> m a), and a function that combines values > of that type with computations that produce values of that type to produce a > new computation for values of that type". > > 1) I know what a type is, but not a "type constructor". I don't normally > think of an Int or even a complex type as being "constructed" except in the > sense of OOP which I know is not what the author means. > > 2) Just *read* the paragraph... "a type constructor, a function that builds > value of that type, and a function that combines values of that type with > computations that produce values of that type to produce a computation of > values of that type" Ugh.... > > > Can anyone recommend a simple and clear explanation of monads? You can > assume that I know basic math and basic Haskell syntax. So, for example, "a > -> b" is much more clear than "a function that takes input of one type and > has an output of a different type". > > Any help would be appreciated. > > Daniel. > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090422/8185017c/attachment-0001.htm From daniel.carrera at theingots.org Wed Apr 22 07:01:46 2009 From: daniel.carrera at theingots.org (Daniel Carrera) Date: Wed Apr 22 06:47:54 2009 Subject: [Haskell-beginners] WWAAA... I hate monads In-Reply-To: <49EEF29C.8010400@theingots.org> References: <49EEEF9A.10307@theingots.org> <49EEF29C.8010400@theingots.org> Message-ID: <49EEF91A.2010109@theingots.org> Daniel Carrera wrote: > Colin Paul Adams wrote: >> This is excellent: >> >> http://ertes.de/articles/monads.html > > Thanks! I'll start reading that page immediately. I noticed that this tutorial points to the following blog: http://byorgey.wordpress.com/2009/01/12/abstraction-intuition-and-the-monad-tutorial-fallacy/ Wow! The author of this blog has nailed it. Trust me, I know, I was a math teacher for years (a *good* teacher, based on student reviews). The author of this blog is exactly right about why most tutorials about abstract concepts are no help (and why so many math teachers are bad). Now I'll go on to read the tutorial, encouraged that the author probably knows how to teach. Cheers, Daniel. From jason.dusek at gmail.com Wed Apr 22 07:26:12 2009 From: jason.dusek at gmail.com (Jason Dusek) Date: Wed Apr 22 07:12:17 2009 Subject: [Haskell-beginners] WWAAA... I hate monads In-Reply-To: <49EEEF9A.10307@theingots.org> References: <49EEEF9A.10307@theingots.org> Message-ID: <42784f260904220426tc165e50m9fa62a97a9603618@mail.gmail.com> 2009/04/22 Daniel Carrera : > I hate monads. Yikes! How do you feel about functors? > 1) I know what a type is, but not a "type constructor". I > don't normally think of an Int or even a complex type as being > "constructed" except in the sense of OOP which I know is not > what the author means. Well, an object constructor takes values and makes a value. A type constructor takes types and makes a type. You've probably seen a few type constructors in your life, for example, `std::vector`, which makes vectors of type `std::vector`. Likewise, `std::map` is a two argument type constructor. > 2) Just *read* the paragraph... "a type constructor, a > function that builds value of that type, and a function that > combines values of that type with computations that produce > values of that type to produce a computation of values of that > type" ? Ugh.... I don't think you should take your first impression too seriously here. The notion of combining computations is really crucial to working with monads; you'll find it's pretty hard to get used to at first, no matter how it's presented. -- Jason Dusek From tom.davie at gmail.com Wed Apr 22 07:42:19 2009 From: tom.davie at gmail.com (Thomas Davie) Date: Wed Apr 22 07:28:27 2009 Subject: [Haskell-beginners] WWAAA... I hate monads In-Reply-To: References: <49EEEF9A.10307@theingots.org> Message-ID: <0DE0C1A3-4344-4AF1-AFBD-70A3F28A81CC@gmail.com> On 22 Apr 2009, at 12:26, Colin Paul Adams wrote: >>>>>> "Daniel" == Daniel Carrera writes: > > Daniel> Can anyone recommend a simple and clear explanation of > Daniel> monads? You can assume that I know basic math and basic > Daniel> Haskell syntax. So, for example, "a -> b" is much more > Daniel> clear than "a function that takes input of one type and > Daniel> has an output of a different type". > > This is excellent: > > http://ertes.de/articles/monads.html Hopefully this will help too - monads are made rather too much of, just build up slowly to them rather than diving into them first ? they're not the be all and end all of classes. http://noordering.wordpress.com/2009/03/31/how-you-shouldnt-use-monad/ Bob From daniel.carrera at theingots.org Wed Apr 22 07:52:14 2009 From: daniel.carrera at theingots.org (Daniel Carrera) Date: Wed Apr 22 07:38:22 2009 Subject: [Haskell-beginners] WWAAA... I hate monads In-Reply-To: References: <49EEEF9A.10307@theingots.org> Message-ID: <49EF04EE.6050505@theingots.org> Andrew Wagner wrote: > Here's a clearer description: > class Monad m where > return :: a -> m a > (>>=) :: m a -> (a -> m b) -> m b > > Instances of Monad must satisfy the following laws: > return a >>= k == k a > m >>= return == m > m >>= (k >>= h) == (m >>= k) >>= h > > Much more clear and concise, don't you think? Actually, that /is/ clearer for me. Though I still think I'll need the tutorial Colin gave me to gain better intuition and understand the motivations behind monads. That said, I do have questions: 1) Am I right in thinking that any type with two elements ("m a") is always a Monad? (IO String, Maybe Int, etc). 2) When I say "m a >>= f" the >>= just pulls the "a" out of "m a" and passes it to "f". Right? 3) The last two properties are not comparing values but functions. Right? For example, reading the second-last property: (m >>= return) :: a -> m a Where (m >>= return) is defined by (\x -> m x >>= return). Right? And this is why you can write the last property: (k >>= h) :: a -> h a defined by (\x -> k a >>= h) This is what allows us to make (k >>= h) the second argument of ">>=" as in the last property: m >>= (k >>= h) == (m >>= k) >>= h Am I right? Thanks, Daniel. From sergey at mikhanov.com Wed Apr 22 08:01:28 2009 From: sergey at mikhanov.com (Sergey V. Mikhanov) Date: Wed Apr 22 07:47:34 2009 Subject: [Haskell-beginners] WWAAA... I hate monads In-Reply-To: <49EF04EE.6050505@theingots.org> References: <49EEEF9A.10307@theingots.org> <49EF04EE.6050505@theingots.org> Message-ID: > 1) Am I right in thinking that any type with two elements ("m a") is always > a Monad? (IO String, Maybe Int, etc). > > 2) When I say "m a >>= f" the >>= just pulls the "a" out of "m a" and passes > it to "f". Right? > > 3) The last two properties are not comparing values but functions. Right? > For example, reading the second-last property: > > (m >>= return) :: a -> m a > > Where (m >>= return) is defined by (\x -> m x >>= return). Right? And this > is why you can write the last property: > > (k >>= h) :: a -> h a defined by (\x -> k a >>= h) This is what allows us to > make (k >>= h) the second argument of ">>=" as in the last property: > > m >>= (k >>= h) == (m >>= k) >>= h > > Am I right? I am also a beginner, so you should take my words with the grain of salt. Strange enough, the monad description that helped me most is the Wikipedia article: http://en.wikipedia.org/wiki/Monad_(functional_programming) This basically answers some of your questions by defining monad as triple (type constructor, bind function and return function), with certain properties. S. From jason.dusek at gmail.com Wed Apr 22 08:31:33 2009 From: jason.dusek at gmail.com (Jason Dusek) Date: Wed Apr 22 08:17:39 2009 Subject: [Haskell-beginners] WWAAA... I hate monads In-Reply-To: <49EF04EE.6050505@theingots.org> References: <49EEEF9A.10307@theingots.org> <49EF04EE.6050505@theingots.org> Message-ID: <42784f260904220531l43f2ef64s4d55146d8f0c8637@mail.gmail.com> 2009/04/22 Daniel Carrera : > 1) Am I right in thinking that any type with two elements > ("m a") is always a Monad? (IO String, Maybe Int, etc). Well, no. Many such types are monads but not all of them. Monads have the monadic operations `return` and `>>=`. > 2) When I say "m a >>= f" the >>= just pulls the "a" out of "m > a" and passes it to "f". Right? Yes. The `>>=` operators defines our evaluation strategy; it allows us to combine computations. Be carefult of confusing `m` (a type constructor) with the value constructors for a particular monad. > 3) The last two properties are not comparing values but > functions. Right? For example, reading the second-last > property: > > (m >>= return) :: a -> m a Not quite -- `someMonadicValue >>= return` is of type `m a`. > Where (m >>= return) is defined by (\x -> m x >>= return). > Right? And this is why you can write the last property: > > (k >>= h) :: a -> h a defined by (\x -> k a >>= h) This is > what allows us to make (k >>= h) the second argument of ">>=" > as in the last property: Actually, the third law is: (m >>= f) >>= g = m >>= (\x -> f x >>= g) -- Jason Dusek From byorgey at seas.upenn.edu Wed Apr 22 08:51:55 2009 From: byorgey at seas.upenn.edu (Brent Yorgey) Date: Wed Apr 22 08:38:00 2009 Subject: [Haskell-beginners] WWAAA... I hate monads In-Reply-To: <49EEF91A.2010109@theingots.org> References: <49EEEF9A.10307@theingots.org> <49EEF29C.8010400@theingots.org> <49EEF91A.2010109@theingots.org> Message-ID: <20090422125155.GA21022@seas.upenn.edu> On Wed, Apr 22, 2009 at 01:01:46PM +0200, Daniel Carrera wrote: > Daniel Carrera wrote: >> Colin Paul Adams wrote: >>> This is excellent: >>> >>> http://ertes.de/articles/monads.html >> Thanks! I'll start reading that page immediately. > > I noticed that this tutorial points to the following blog: > > http://byorgey.wordpress.com/2009/01/12/abstraction-intuition-and-the-monad-tutorial-fallacy/ > > Wow! The author of this blog has nailed it. Trust me, I know, I was a math > teacher for years (a *good* teacher, based on student reviews). The author > of this blog is exactly right about why most tutorials about abstract > concepts are no help (and why so many math teachers are bad). Thanks! =) You may also be interested in taking a look at the Typeclassopedia, in issue 13 of the Monad.Reader. http://haskell.org/haskellwiki/The_Monad.Reader -Brent From daniel.carrera at theingots.org Wed Apr 22 09:17:03 2009 From: daniel.carrera at theingots.org (Daniel Carrera) Date: Wed Apr 22 09:03:13 2009 Subject: [Haskell-beginners] WWAAA... I hate monads In-Reply-To: <42784f260904220531l43f2ef64s4d55146d8f0c8637@mail.gmail.com> References: <49EEEF9A.10307@theingots.org> <49EF04EE.6050505@theingots.org> <42784f260904220531l43f2ef64s4d55146d8f0c8637@mail.gmail.com> Message-ID: <49EF18CF.2060708@theingots.org> Jason Dusek wrote: > Actually, the third law is: > > (m >>= f) >>= g == m >>= (\x -> f x >>= g) Yeah. I just saw that in the tutorial. And it actually makes more sense that way (esp after reading some of the tutorial): 1) A "computation" is something that may have a result. 2) In "m >>= f", m is a computation and f is a function that takes a value and returns a computation. >>= takes the output of m and makes it the input of f. 3) Therefore, the value of "m >>= f" is a computation. 4) Because "m >>= f" is a computation, it can be the left parameter of another >>=, as in "(m >>= f) >>= g". 5) If "x" is a value then "f x" is a computation. Thus, "f x" can be the left parameter of >>=, as in "f x >>= g", and the result of that is a computation. 6) Therefore, (\x -> f x >>= g) is a function that takes a value ("x") and returns a computation, so it can be the right parameter of >>=. I think I get it (at least this part). Cheers, Daniel. From daniel.carrera at theingots.org Wed Apr 22 16:38:14 2009 From: daniel.carrera at theingots.org (Daniel Carrera) Date: Wed Apr 22 16:24:25 2009 Subject: [Haskell-beginners] computation vs function Message-ID: <49EF8036.7020503@theingots.org> Hello, I have finished the tutorial at http://ertes.de/articles/monads.html and my understanding of monads has increased greatly. I still need to cement some concepts in my mind. What exactly is the difference between a computation and a function? Monads revolve around computations, so I'd like to understand computations better. Thanks for the help. Daniel. From byorgey at seas.upenn.edu Wed Apr 22 16:46:07 2009 From: byorgey at seas.upenn.edu (Brent Yorgey) Date: Wed Apr 22 16:32:11 2009 Subject: [Haskell-beginners] computation vs function In-Reply-To: <49EF8036.7020503@theingots.org> References: <49EF8036.7020503@theingots.org> Message-ID: <20090422204607.GA1419@seas.upenn.edu> On Wed, Apr 22, 2009 at 10:38:14PM +0200, Daniel Carrera wrote: > Hello, > > I have finished the tutorial at http://ertes.de/articles/monads.html and my > understanding of monads has increased greatly. I still need to cement some > concepts in my mind. What exactly is the difference between a computation > and a function? Monads revolve around computations, so I'd like to > understand computations better. "Computation" does not really have any technical meaning, it's just supposed to be an intuition. But the term "computation" is often used to refer to things of type (m a) where m is a Monad. You can clearly see from the types that something of type (m a) is different than something of type (a -> b). The former takes no inputs and somehow produces value(s) of type a; the latter takes something of type a as input and produces something of type b as output. However, you could also legitimately thing of things of type (a -> b) as "computations"; more interestingly, you can think of things of type (a -> m b) as "parameterized computations" which can be composed in nice ways. Don't rely too heavily on the "computation" idea; monads certainly don't "revolve around computations", it's only one particular way of giving intuition for monads which does. -Brent From daniel.carrera at theingots.org Wed Apr 22 17:06:02 2009 From: daniel.carrera at theingots.org (Daniel Carrera) Date: Wed Apr 22 16:52:12 2009 Subject: [Haskell-beginners] computation vs function In-Reply-To: <20090422204607.GA1419@seas.upenn.edu> References: <49EF8036.7020503@theingots.org> <20090422204607.GA1419@seas.upenn.edu> Message-ID: <49EF86BA.7010402@theingots.org> Brent Yorgey wrote: > "Computation" does not really have any technical meaning, it's just > supposed to be an intuition. But the term "computation" is often used > to refer to things of type (m a) where m is a Monad. You can clearly > see from the types that something of type (m a) is different than > something of type (a -> b). The former takes no inputs and somehow > produces value(s) of type a; the latter takes something of type a as > input and produces something of type b as output. > > However, you could also legitimately thing of things of type (a -> b) > as "computations"; more interestingly, you can think of things of type > (a -> m b) as "parameterized computations" which can be composed in > nice ways. > > Don't rely too heavily on the "computation" idea; monads certainly > don't "revolve around computations", it's only one particular way of > giving intuition for monads which does. Thanks. That helps a lot. It looks to me that one could replace the word "computation" everywhere in the article with "monadic type" (where again, "monadic type" is just an intuition for "m a" where m is a Monad) and the article would be equally correct. Am I right? The Wikipedia article seems to use "monadic type" for the same things that ertes calls "computation". I can't decide which term gives better intuition. The term "computation" makes binding more intuitive: The computation (m a) returns a value of type "a" can then be fed into a function of type (a -> m b). On the other hand, "monadic type" is more intuitive when you write "Maybe Int" or "IO String". Anyways, thanks for the help. I'm (slowly) making progress. Cheers, Daniel. From wagner.andrew at gmail.com Wed Apr 22 17:13:42 2009 From: wagner.andrew at gmail.com (Andrew Wagner) Date: Wed Apr 22 16:59:46 2009 Subject: [Haskell-beginners] computation vs function In-Reply-To: <49EF86BA.7010402@theingots.org> References: <49EF8036.7020503@theingots.org> <20090422204607.GA1419@seas.upenn.edu> <49EF86BA.7010402@theingots.org> Message-ID: I kind of like the term "monadic action" myself. Here's another perspective that may help you out: I really like the idea of the "programmable semicolon". That is, in your typical programming languages, you're really working in an implicit State monad. All the in-scope state is carried over from line to line, and each line is separated by a semicolon. In Haskell, we first get rid of this. We don't like the idea of being able to modify state without being explicit about the types. But of course we still allow you to carry state around. You use >>= to bind "lines" together to use the same state. That's when you get to really take things a step further, though: because state isn't the only "side effect" which you can capture and hide away in a >>=. You can do it with IO, non-determinism, potential failure, etc., etc. And that's where monads come in. It's an interface for gluing together actions with "side effects" in a way in which the actual effects are explicit, but hidden away in the class instance. Hope this helps! On Wed, Apr 22, 2009 at 5:06 PM, Daniel Carrera < daniel.carrera@theingots.org> wrote: > Brent Yorgey wrote: > >> "Computation" does not really have any technical meaning, it's just >> supposed to be an intuition. But the term "computation" is often used >> to refer to things of type (m a) where m is a Monad. You can clearly >> see from the types that something of type (m a) is different than >> something of type (a -> b). The former takes no inputs and somehow >> produces value(s) of type a; the latter takes something of type a as >> input and produces something of type b as output. >> >> However, you could also legitimately thing of things of type (a -> b) >> as "computations"; more interestingly, you can think of things of type >> (a -> m b) as "parameterized computations" which can be composed in >> nice ways. >> >> Don't rely too heavily on the "computation" idea; monads certainly >> don't "revolve around computations", it's only one particular way of >> giving intuition for monads which does. >> > > Thanks. That helps a lot. > > It looks to me that one could replace the word "computation" everywhere in > the article with "monadic type" (where again, "monadic type" is just an > intuition for "m a" where m is a Monad) and the article would be equally > correct. Am I right? > > The Wikipedia article seems to use "monadic type" for the same things that > ertes calls "computation". > > I can't decide which term gives better intuition. The term "computation" > makes binding more intuitive: The computation (m a) returns a value of type > "a" can then be fed into a function of type (a -> m b). On the other hand, > "monadic type" is more intuitive when you write "Maybe Int" or "IO String". > > Anyways, thanks for the help. I'm (slowly) making progress. > > Cheers, > Daniel. > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090422/da872308/attachment.htm From daniel.is.fischer at web.de Wed Apr 22 17:54:44 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Wed Apr 22 17:41:11 2009 Subject: [Haskell-beginners] computation vs function In-Reply-To: <49EF86BA.7010402@theingots.org> References: <49EF8036.7020503@theingots.org> <20090422204607.GA1419@seas.upenn.edu> <49EF86BA.7010402@theingots.org> Message-ID: <200904222354.44650.daniel.is.fischer@web.de> Am Mittwoch 22 April 2009 23:06:02 schrieb Daniel Carrera: > The Wikipedia article seems to use "monadic type" for the same things > that ertes calls "computation". > > I can't decide which term gives better intuition. The term "computation" > makes binding more intuitive: The computation (m a) returns a value of > type "a" can then be fed into a function of type (a -> m b). On the > other hand, "monadic type" is more intuitive when you write "Maybe Int" > or "IO String". Yes, different expressions give better pictures for different aspects. I think the term computation is meant to hint that the computations in one monad share a common structure, much more so than general functions, so a different term was chosen. Of course computations in different monads have different structures, but even these have common aspects (which are then captured in the Monad type class). > > Anyways, thanks for the help. I'm (slowly) making progress. > > Cheers, > Daniel. Cheers, Daniel From flippa at flippac.org Wed Apr 22 17:59:07 2009 From: flippa at flippac.org (Philippa Cowderoy) Date: Wed Apr 22 17:45:24 2009 Subject: [Haskell-beginners] computation vs function In-Reply-To: References: <49EF8036.7020503@theingots.org> <20090422204607.GA1419@seas.upenn.edu> <49EF86BA.7010402@theingots.org> Message-ID: <1240437547.16004.5.camel@flippa-eee> On Wed, 2009-04-22 at 17:13 -0400, Andrew Wagner wrote: > I kind of like the term "monadic action" myself. Action's great for IO, but it's less so for monads like lists that aren't particularly about imperative ideas of computation. I still talk about IO actions though. -- Philippa Cowderoy From flippa at flippac.org Wed Apr 22 18:00:05 2009 From: flippa at flippac.org (Philippa Cowderoy) Date: Wed Apr 22 17:46:18 2009 Subject: [Haskell-beginners] computation vs function In-Reply-To: <49EF86BA.7010402@theingots.org> References: <49EF8036.7020503@theingots.org> <20090422204607.GA1419@seas.upenn.edu> <49EF86BA.7010402@theingots.org> Message-ID: <1240437605.16004.6.camel@flippa-eee> On Wed, 2009-04-22 at 23:06 +0200, Daniel Carrera wrote: > It looks to me that one could replace the word "computation" everywhere > in the article with "monadic type" (where again, "monadic type" is just > an intuition for "m a" where m is a Monad) and the article would be > equally correct. Am I right? > Maybe for that article, but generally it's the values that are computations, not the types. -- Philippa Cowderoy From flippa at flippac.org Wed Apr 22 18:01:50 2009 From: flippa at flippac.org (Philippa Cowderoy) Date: Wed Apr 22 17:48:00 2009 Subject: [Haskell-beginners] computation vs function In-Reply-To: <49EF8036.7020503@theingots.org> References: <49EF8036.7020503@theingots.org> Message-ID: <1240437710.16004.8.camel@flippa-eee> On Wed, 2009-04-22 at 22:38 +0200, Daniel Carrera wrote: > Hello, > > I have finished the tutorial at http://ertes.de/articles/monads.html and > my understanding of monads has increased greatly. I still need to cement > some concepts in my mind. What exactly is the difference between a > computation and a function? Monads revolve around computations, so I'd > like to understand computations better. > Computations are like "procedures" in other languages - you run them[1], they yield a value. Conceptually, functions are (potentially infinite) maps from their input to their output. We sometimes call functions with types like "Int -> IO ()" monadic functions as well, which may also mean the combination of the function and then the computation that results - by analogy to functions in languages like C. [1] Sometimes the runtime system runs them for you, like main. Sometimes the computation is already its (lazily evaluated) output, like with lists or Maybe. -- Philippa Cowderoy From es at ertes.de Wed Apr 22 19:10:28 2009 From: es at ertes.de (Ertugrul Soeylemez) Date: Wed Apr 22 18:55:56 2009 Subject: [Haskell-beginners] Re: computation vs function References: <49EF8036.7020503@theingots.org> Message-ID: <20090423011028.1724247c@tritium.xx> Daniel Carrera wrote: > I have finished the tutorial at http://ertes.de/articles/monads.html > and my understanding of monads has increased greatly. I still need to > cement some concepts in my mind. What exactly is the difference > between a computation and a function? Monads revolve around > computations, so I'd like to understand computations better. What I refer to as a 'computation' in the article is actually just a value of type 'Monad m => m a'. I have chosen that term, because you can apply it to any monad I've seen. As mentioned in section 5, you can think of 'Just 3' as being a computation, which results in 3. But it's important that this is not a function, but just an independent value. You can think of a function of type 'a -> b' as a parametric value -- a value of type 'b' depending on some value of type 'a'. That makes a function of type 'Monad m => a -> m b' a parametric computation. A computation, where something is missing, like with an open slot, where you need to plug a cable in first. By the way, this is where (>>=) comes into play. If you have a computation, which needs a value, but that value comes as the result of another computation, you can use the binding operator. f :: Monad m => a -> m b The 'f' function is a parametric computation of type 'm b', which depends on a value of type 'a'. Now if c :: Monad m => m a and 'm' and 'a' in 'f' are the same as 'm' and 'a' in 'c', then c >>= f takes 'c', puts its result (of type 'a') into 'f', resulting in a computation of type 'm b'. Example: You have a computation 'myComp', which outputs a string to stdout prefixed with "+++ ": myComp :: String -> IO () myComp str = putStrLn ("+++ " ++ str) If that string is available directly, just pass it to 'myComp', which results in a computation. If that string is not available directly, but comes as the result of another computation 'getLine', you use (>>=): getLine >>= myComp Greets, Ertugrul. -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://blog.ertes.de/ From flopticalogic at gmail.com Thu Apr 23 01:59:37 2009 From: flopticalogic at gmail.com (Floptical Logic) Date: Thu Apr 23 01:45:40 2009 Subject: [Haskell-beginners] doing state right Message-ID: I am using a PPM library to generate a square image where each white pixel represents a prime number. The PPM library takes a function (Int -> Int -> Colour) to create the image. This interface isn't ideal but it is what I have to work with. I am convinced that using a sieve is faster than testing every pixel in the image for primality, but the (Int -> Int -> Colour) interface makes this awkward. The code below attempts to treat the list of prime numbers as a stack via global mutable state, popping the head whenever the pixel is prime. Obviously this is not idiomatic Haskell. What is the correct approach of dealing with state here? Thanks for reading. import ONeillPrimes import PPM6 import Colour import Data.IORef import System.IO.Unsafe limit = 2000 slimit = limit*limit primeList = takeWhile (<=slimit) primes p :: IORef [Int] p = unsafePerformIO (newIORef primeList) pcol n = unsafePerformIO $ do xs <- readIORef p if null xs then return black else if n == head xs then do writeIORef p (tail xs) return white else return black main = quick_ppm "foo.ppm" (\i j -> pcol ((i-1)*limit+j)) limit limit -- quick_ppm :: FilePath -> (Int -> Int -> Colour.Colour) -> Int -> Int -> IO () From quentin.moser at unifr.ch Thu Apr 23 02:55:47 2009 From: quentin.moser at unifr.ch (Quentin Moser) Date: Thu Apr 23 02:40:49 2009 Subject: [Haskell-beginners] doing state right In-Reply-To: References: Message-ID: <20090423085547.3f3ecda0@unifr.ch> On Thu, 23 Apr 2009 00:59:37 -0500 Floptical Logic wrote: > I am using a PPM library to generate a square image where each white > pixel represents a prime number. The PPM library takes a function > (Int -> Int -> Colour) to create the image. This interface isn't > ideal but it is what I have to work with. I am convinced that using a > sieve is faster than testing every pixel in the image for primality, > but the (Int -> Int -> Colour) interface makes this awkward. The code > below attempts to treat the list of prime numbers as a stack via > global mutable state, popping the head whenever the pixel is prime. > Obviously this is not idiomatic Haskell. What is the correct approach > of dealing with state here? Thanks for reading. > > import ONeillPrimes > import PPM6 > import Colour > > import Data.IORef > import System.IO.Unsafe > > limit = 2000 > slimit = limit*limit > > primeList = takeWhile (<=slimit) primes > > p :: IORef [Int] > p = unsafePerformIO (newIORef primeList) > > pcol n = unsafePerformIO $ do > xs <- readIORef p > if null xs then return black else > if n == head xs > then do > writeIORef p (tail xs) > return white > else > return black > > main = quick_ppm "foo.ppm" (\i j -> pcol ((i-1)*limit+j)) limit limit > > -- quick_ppm :: FilePath -> (Int -> Int -> Colour.Colour) -> Int -> > Int -> IO () _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners Since Haskell is a pure language, the type (Int -> Int -> Colour) means that the result of the function will _only_ depend on its Int parameters. Not on some external state, not even on the order of execution. Using unsafePerformIO to nevertheless fit a dependency on state in such a function, like you did, is extremely dangerous. First of all, the interface to quick_ppm makes absolutely no guarantee regarding the order in which the colors of the different pixels will be evaluated; after all, it simply shouldn't matter. Second, and worse, a function such as pcol risks breaking compiler optimisations that rely on its purity. The fact that your current program actually happens to work (if it does) is simply a stroke of luck. The bottom-line is: the quick_ppm interface is simply too restrictive to implement your algorithm. You'll have to either - Find another function in the library with a more flexible type. - Drop the optimisation and search the whole primes list from the beginning every time (urk!). As for the proper use of unsafePerformIO: Referential transparency (the fact that a function, called with the same arguments, will always produce the same result) is not just a safety restriction; it's a fundamental part of the semantics of Haskell, and compilers rely heavily on it. Using unsafePerformIO to create an unpure function means breaking the language's semantics, which will result in misbehaving or segfaulting code. So that's definitely not what unsafePerformIO is for. You should instead only use it when you can _prove_ that the resulting function will actually be referentially transparent, i.e. whatever side-effects it uses are purely local and don't affect the rest of the program at all. From apfelmus at quantentunnel.de Thu Apr 23 03:03:19 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Thu Apr 23 02:49:36 2009 Subject: [Haskell-beginners] Re: WWAAA... I hate monads In-Reply-To: <49EEEF9A.10307@theingots.org> References: <49EEEF9A.10307@theingots.org> Message-ID: Daniel Carrera wrote: > 1) I know what a type is, but not a "type constructor". I don't normally > think of an Int or even a complex type as being "constructed" except in > the sense of OOP which I know is not what the author means. [Int] is a type. [] itself is a type constructor, taking a type like Int and "constructing" a new type [Int] , a list of integers. In other words, a type constructor is like a function on types. Regards, apfelmus -- http://apfelmus.nfshost.com From chaddai.fouche at gmail.com Thu Apr 23 04:03:50 2009 From: chaddai.fouche at gmail.com (=?UTF-8?B?Q2hhZGRhw68gRm91Y2jDqQ==?=) Date: Thu Apr 23 03:49:53 2009 Subject: [Haskell-beginners] doing state right In-Reply-To: References: Message-ID: On Thu, Apr 23, 2009 at 7:59 AM, Floptical Logic wrote: > I am using a PPM library to generate a square image where each white > pixel represents a prime number. ?The PPM library takes a function > (Int -> Int -> Colour) to create the image. ?This interface isn't > ideal but it is what I have to work with. ?I am convinced that using a > sieve is faster than testing every pixel in the image for primality, > but the (Int -> Int -> Colour) interface makes this awkward. Only because you're still not familiar with arrays in Haskell, this interface is absolutely not a problem : main = quick_ppm "foo.ppm" (\i j -> isPrime ((i-1)*limit+j)) limit limit where isPrime n = primeSieve ! n primeSieve :: UArray Int Bool primeSieve = accumArray (\_ _ -> True) False (0,limit*limit) $ zip primes (repeat ()) There are in fact algorithms that would directly do the sieve on an array (the classical algorithm would do nicely) but if you don't need exceedingly good performance, that will do. -- Jeda? From chaddai.fouche at gmail.com Thu Apr 23 04:05:41 2009 From: chaddai.fouche at gmail.com (=?UTF-8?B?Q2hhZGRhw68gRm91Y2jDqQ==?=) Date: Thu Apr 23 03:51:45 2009 Subject: [Haskell-beginners] doing state right In-Reply-To: References: Message-ID: On Thu, Apr 23, 2009 at 10:03 AM, Chadda? Fouch? wrote: > > main = quick_ppm "foo.ppm" (\i j -> isPrime ((i-1)*limit+j)) limit limit > ?where > ? ?isPrime n = primeSieve ! n > ? ?primeSieve :: UArray Int Bool > ? ?primeSieve = accumArray (\_ _ -> True) False (0,limit*limit) $ zip > primes (repeat ()) > That should read as "zip (takeWhile (<= limit*limit) primes) (repeat ())" of course. -- Jeda? From aruiz at um.es Thu Apr 23 04:47:44 2009 From: aruiz at um.es (Alberto Ruiz) Date: Thu Apr 23 04:33:51 2009 Subject: [Haskell-beginners] problem cabal install'ing hmatrix In-Reply-To: References: <49ED7A6A.5090103@um.es> Message-ID: <49F02B30.8090000@um.es> Hi Erik, Probably a dependency not mentionend in extra-libraries is missing. There is not a standard way to link -llapack. For instance, in Ubuntu/Debian we only need gsl and lapack: $ ld -lgsl -llapack ld: warning: cannot find entry symbol _start; not setting start address This means that everything is ok, but in other systems we may also need some of -l[gsl]cblas, -lgfortran, or -lf77blas, -latlas, -lgcc_s, etc. Try to find the correct libraries with $ ld -lgsl -llapack -lgslcblas or other combinations, and modify the extra-libraries field in hmatrix.cabal. In any case, I will try to add cabal flags to cover common situations. (There is also a possible issue with ghc-6.8 that must be fixed, but the library should work ok with 6.10). Alberto PS: I CC the list for reference. Erik Quaeghebeur wrote: > Alberto, > > Original message: >>> >>> $ cabal install hmatrix >>> Resolving dependencies... >>> Configuring hmatrix-0.5.1.1... >>> Preprocessing library hmatrix-0.5.1.1... >>> running dist/build/Numeric/GSL/Special/Internal_hsc_make failed >>> command was: dist/build/Numeric/GSL/Special/Internal_hsc_make >>> > dist/build/Numeric/GSL/Special/Internal.hs >>> cabal: Error: some packages failed to install: >>> hmatrix-0.5.1.1 failed during the building phase. The exception was: >>> exit: ExitFailure 1 >>> >>> What should I do to diagnose/resolve this problem? > > On Tue, 21 Apr 2009, Alberto Ruiz wrote: >> >> Erik, do you have the same problem with a previous version? >> >> cabal install hmatrix-0.5.0.1 > > Thanks for your (speedy) reply. Yes it gives the same problem: > > $ cabal install hmatrix-0.5.0.1 > Resolving dependencies... > Configuring hmatrix-0.5.0.1... > Preprocessing library hmatrix-0.5.0.1... > running dist/build/Numeric/GSL/Special/Internal_hsc_make failed > command was: dist/build/Numeric/GSL/Special/Internal_hsc_make >> dist/build/Numeric/GSL/Special/Internal.hs > cabal: Error: some packages failed to install: > hmatrix-0.5.0.1 failed during the building phase. The exception was: > exit: ExitFailure 1 > > Also, suggested by Heinrich Apfelmus: > > $ cabal install hmatrix --verbose > /usr/bin/ghc --numeric-version > looking for package tool: ghc-pkg near compiler in /usr/bin > found package tool in /usr/bin/ghc-pkg > /usr/bin/ghc-pkg --version > /usr/bin/ghc --supported-languages > Reading installed packages... > /usr/bin/ghc-pkg list > Reading available packages... > Resolving dependencies... > selecting hmatrix-0.5.1.1 (hackage) and discarding hmatrix-0.1.0.0, > 0.1.1.0, > 0.2.0.0, 0.2.1.0, 0.3.0.0, 0.4.0.0 and 0.5.0.1 > selecting base-3.0.1.0 (installed) > selecting rts-1.0 (installed) > selecting storable-complex-0.2 (installed or hackage) and discarding > storable-complex-0.1 > selecting haskell98-1.0.1.0 (installed or hackage) and discarding > haskell98-1.0 > selecting process-1.0.0.0 (installed or hackage) and discarding > process-1.0.1.1 > selecting unix-2.3.0.0 (installed or hackage) and discarding unix-2.0, > 2.2.0.0, 2.3.1.0 and 2.3.2.0 > selecting directory-1.0.0.0 (installed or hackage) and discarding > directory-1.0.0.3 > selecting filepath-1.1.0.0 (installed or hackage) and discarding > filepath-1.0, > 1.1.0.1 and 1.1.0.2 > selecting array-0.1.0.0 (installed or hackage) and discarding array-0.2.0.0 > selecting QuickCheck-1.2.0.0 (installed or hackage) and discarding > QuickCheck-1.0, 1.1.0.0, 2.1 and 2.1.0.1 > selecting random-1.0.0.0 (installed or hackage) and discarding > random-1.0.0.1 > selecting old-time-1.0.0.0 (installed or hackage) and discarding > old-time-1.0.0.2 > selecting old-locale-1.0.0.0 (installed or hackage) and discarding > old-locale-1.0.0.1 > selecting HUnit-1.2.0.3 (installed or hackage) and discarding HUnit-1.1, > 1.2.0.0, 1.2.0.1 and 1.2.0.2 > In order, the following would be installed: > hmatrix-0.5.1.1 (new package) > hmatrix-0.5.1.1 has already been downloaded. > Extracting > /home/equaeghe/.cabal/packages/hackage.haskell.org/hmatrix/0.5.1.1/hmatrix-0.5.1.1.tar.gz > > to /tmp/hmatrix-0.5.1.16320... > Configuring hmatrix-0.5.1.1... > Flags chosen: unsafe=False, accelerate=False, mkl=False, splitbase=True > Dependency HUnit -any && ==1.2.0.3: using HUnit-1.2.0.3 > Dependency QuickCheck -any && ==1.2.0.0: using QuickCheck-1.2.0.0 > Dependency array -any && ==0.1.0.0: using array-0.1.0.0 > Dependency base >=3 && ==3.0.1.0: using base-3.0.1.0 > Dependency haskell98 -any && ==1.0.1.0: using haskell98-1.0.1.0 > Dependency storable-complex -any && ==0.2: using storable-complex-0.2 > Using Cabal-1.6.0.3 compiled by ghc-6.8 > Using compiler: ghc-6.8.2 > Using install prefix: /home/equaeghe/.cabal > Binaries installed in: /home/equaeghe/.cabal/bin > Libraries installed in: /home/equaeghe/.cabal/lib/hmatrix-0.5.1.1/ghc-6.8.2 > Private binaries installed in: /home/equaeghe/.cabal/libexec > Data files installed in: /home/equaeghe/.cabal/share/hmatrix-0.5.1.1 > Documentation installed in: /home/equaeghe/.cabal/share/doc/hmatrix-0.5.1.1 > No alex found > Using ar found on system at: /usr/bin/ar > No c2hs found > No cpphs found > No ffihugs found > Using gcc version 4.3.2 found on system at: /usr/bin/gcc > Using ghc version 6.8.2 found on system at: /usr/bin/ghc > Using ghc-pkg version 6.8.2 found on system at: /usr/bin/ghc-pkg > No greencard found > No haddock found > No happy found > No hmake found > Using hsc2hs version 0.66 found on system at: /usr/bin/hsc2hs > No hscolour found > No hugs found > No jhc found > Using ld found on system at: /usr/bin/ld > No nhc98 found > Using pkg-config version 0.23 found on system at: /usr/bin/pkg-config > Using ranlib found on system at: /usr/bin/ranlib > Using strip found on system at: /usr/bin/strip > Using tar found on system at: /bin/tar > /usr/bin/gcc /tmp/6320.c -o /tmp/6320 -D__GLASGOW_HASKELL__=608 -I. > -DFINIT -I/usr/lib64/ghc-6.8.2/lib/process-1.0.0.0/include > -I/usr/lib64/ghc-6.8.2/lib/unix-2.3.0.0/include > -I/usr/lib64/ghc-6.8.2/lib/directory-1.0.0.0/include > -I/usr/lib64/ghc-6.8.2/lib/old-time-1.0.0.0/include > -I/usr/lib64/ghc-6.8.2/lib/base-3.0.1.0/include > -I/usr/lib64/ghc-6.8.2/include -lgsl -llapack > Creating dist/build (and its parents) > Creating dist/build/autogen (and its parents) > Preprocessing library hmatrix-0.5.1.1... > Creating dist/build/Numeric/GSL/Special (and its parents) > /usr/bin/hsc2hs --cc=/usr/bin/gcc --ld=/usr/bin/gcc > --cflag=-D__GLASGOW_HASKELL__=608 --cflag=-DFINIT --lflag=-lgsl > --lflag=-llapack > --cflag=-I/usr/lib64/ghc-6.8.2/lib/process-1.0.0.0/include > --cflag=-I/usr/lib64/ghc-6.8.2/lib/unix-2.3.0.0/include > --cflag=-I/usr/lib64/ghc-6.8.2/lib/directory-1.0.0.0/include > --cflag=-I/usr/lib64/ghc-6.8.2/lib/old-time-1.0.0.0/include > --cflag=-I/usr/lib64/ghc-6.8.2/lib/base-3.0.1.0/include > --cflag=-I/usr/lib64/ghc-6.8.2/include > --lflag=-L/home/equaeghe/.cabal/lib/storable-complex-0.2/ghc-6.8.2 > --lflag=-L/usr/lib64/ghc-6.8.2/lib/haskell98-1.0.1.0 > --lflag=-L/usr/lib64/ghc-6.8.2/lib/process-1.0.0.0 > --lflag=-L/usr/lib64/ghc-6.8.2/lib/unix-2.3.0.0 --lflag=-lutil > --lflag=-ldl --lflag=-L/usr/lib64/ghc-6.8.2/lib/directory-1.0.0.0 > --lflag=-L/usr/lib64/ghc-6.8.2/lib/filepath-1.1.0.0 > --lflag=-L/usr/lib64/ghc-6.8.2/lib/array-0.1.0.0 > --lflag=-L/home/equaeghe/.cabal/lib/QuickCheck-1.2.0.0/ghc-6.8.2 > --lflag=-L/usr/lib64/ghc-6.8.2/lib/random-1.0.0.0 > --lflag=-L/usr/lib64/ghc-6.8.2/lib/old-time-1.0.0.0 > --lflag=-L/usr/lib64/ghc-6.8.2/lib/old-locale-1.0.0.0 > --lflag=-L/home/equaeghe/.cabal/lib/HUnit-1.2.0.3/ghc-6.8.2 > --lflag=-L/usr/lib64/ghc-6.8.2/lib/base-3.0.1.0 > --lflag=-L/usr/lib64/ghc-6.8.2 --lflag=-lm --lflag=-lgmp --lflag=-ldl > --lflag=-lrt -o dist/build/Numeric/GSL/Special/Internal.hs > lib/Numeric/GSL/Special/Internal.hsc > running dist/build/Numeric/GSL/Special/Internal_hsc_make failed > command was: dist/build/Numeric/GSL/Special/Internal_hsc_make >> dist/build/Numeric/GSL/Special/Internal.hs > cabal: Error: some packages failed to install: > hmatrix-0.5.1.1 failed during the building phase. The exception was: > exit: ExitFailure 1 > > I still have to test the version in the Gentoo Haskell overlay. That > should work (but then I wouldn't use cabal install). > > Regards, > > Erik > From sam.martin at geomerics.com Thu Apr 23 04:51:43 2009 From: sam.martin at geomerics.com (Sam Martin) Date: Thu Apr 23 04:37:48 2009 Subject: [Haskell-beginners] WWAAA... I hate monads In-Reply-To: <0DE0C1A3-4344-4AF1-AFBD-70A3F28A81CC@gmail.com> References: <49EEEF9A.10307@theingots.org> <0DE0C1A3-4344-4AF1-AFBD-70A3F28A81CC@gmail.com> Message-ID: > This is excellent: > > http://ertes.de/articles/monads.html Wow. That really is a great tutorial! Suddenly the world becomes clear... Definitely gets my vote as must read material. Cheers, Sam From daniel.carrera at theingots.org Thu Apr 23 05:10:40 2009 From: daniel.carrera at theingots.org (Daniel Carrera) Date: Thu Apr 23 04:56:52 2009 Subject: [Haskell-beginners] WWAAA... I hate monads In-Reply-To: References: <49EEEF9A.10307@theingots.org> <0DE0C1A3-4344-4AF1-AFBD-70A3F28A81CC@gmail.com> Message-ID: <49F03090.7070505@theingots.org> Sam Martin wrote: >> This is excellent: >> >> http://ertes.de/articles/monads.html > > Wow. That really is a great tutorial! Suddenly the world becomes > clear... > > Definitely gets my vote as must read material. +1 I was very impressed too. And I am not easy to impress when it comes to documentation. I plan to read it a second time to solidify some of the ideas, but on my first reading my understanding of Monads increased by leaps and bounds. Ertugrul deserves to be commended, and this tutorial should be made more prominent on haskell.org. Daniel. From colin at colina.demon.co.uk Thu Apr 23 05:25:03 2009 From: colin at colina.demon.co.uk (Colin Paul Adams) Date: Thu Apr 23 05:11:18 2009 Subject: [Haskell-beginners] WWAAA... I hate monads In-Reply-To: <49F03090.7070505@theingots.org> (Daniel Carrera's message of "Thu\, 23 Apr 2009 11\:10\:40 +0200") References: <49EEEF9A.10307@theingots.org> <0DE0C1A3-4344-4AF1-AFBD-70A3F28A81CC@gmail.com> <49F03090.7070505@theingots.org> Message-ID: >>>>> "Daniel" == Daniel Carrera writes: Daniel> Sam Martin wrote: >>> This is excellent: >>> >>> http://ertes.de/articles/monads.html >> >> Wow. That really is a great tutorial! Suddenly the world >> becomes clear... >> >> Definitely gets my vote as must read material. Daniel> +1 Daniel> I was very impressed too. And I am not easy to impress Daniel> when it comes to documentation. I plan to read it a second Daniel> time to solidify some of the ideas, but on my first Daniel> reading my understanding of Monads increased by leaps and Daniel> bounds. Daniel> Ertugrul deserves to be commended, and this tutorial Daniel> should be made more prominent on haskell.org. I think so. I've read VERY MANY tutorials on monads, and they were all confusing - except this one. -- Colin Adams Preston Lancashire From daniel.carrera at theingots.org Thu Apr 23 05:32:41 2009 From: daniel.carrera at theingots.org (Daniel Carrera) Date: Thu Apr 23 05:18:50 2009 Subject: [Haskell-beginners] Re: computation vs function In-Reply-To: <20090423011028.1724247c@tritium.xx> References: <49EF8036.7020503@theingots.org> <20090423011028.1724247c@tritium.xx> Message-ID: <49F035B9.8090502@theingots.org> Ertugrul Soeylemez wrote: > What I refer to as a 'computation' in the article is actually just a > value of type 'Monad m => m a'. I have chosen that term, because you > can apply it to any monad I've seen. As mentioned in section 5, you can > think of 'Just 3' as being a computation, which results in 3. But it's > important that this is not a function, but just an independent value. Thanks. I think the article would benefit from making the meaning of computation clearer. The word computation appears in the tutorial 51 times before section 5. That means that when I tried to go back for a definition of computation I couldn't find one. The first place you use the word computation is in the preamble, but that's not a good place to define terms. The second time you use the word computation is in section 2 "Motivation". This might be a good place to define the term. The Motivation section already defines several terms (referentially transparent, purely functional, etc), so it seems like a good place to define computation as well. In section 2 we can't say "Monad => m a" or "Just 3" because the terms are not introduced yet. Perhaps you could say something like this: The word 'computation' here is not a technical term. I use it to refer to something that returns a value without taking in any parameters. For example (m a) is a computation that takes no parameters but returns a value of type 'a' whereas (a -> b) is a function that takes a parameter of type 'a' and returns a value of type 'b'. It is important that a computation is not a function, but an independent value. I think that adding that as the third paragraph in the Motivation section would be helpful. In addition, in the Preamble, when you use the word computation, I would add "(see next section)". Question: Would it be reasonable to say that a computation is a wrapper? I'm not sure, because I don't know if a computation always results in the *same* value (you know, side-effects). I know that "Just 3" always results in 3, but is that universal? Cheers, Daniel. From daniel.carrera at theingots.org Thu Apr 23 08:57:58 2009 From: daniel.carrera at theingots.org (Daniel Carrera) Date: Thu Apr 23 08:57:10 2009 Subject: [Haskell-beginners] Help with types Message-ID: <49F065D6.1080300@theingots.org> Hi, I want to make a simple "average" function: average xs = (sum xs)/(length xs) When I try that on ghci I get the following error: No instance for (Fractional Int) arising from a use of `/' at :1:17-36 Possible fix: add an instance declaration for (Fractional Int) In the expression: (sum xs) / (length xs) In the definition of `average': average xs = (sum xs) / (length xs) Ok, so 'sum' is of type (Num a => [a] -> a), length is of type ([a] -> Int) and (/) is of type (Fractional a => a -> a -> a). Can someone explain how I can "add an instance declaration" to my function so as to make all these types compatible? Thanks, Daniel. From daniel.is.fischer at web.de Thu Apr 23 09:35:12 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Thu Apr 23 09:21:33 2009 Subject: [Haskell-beginners] Help with types In-Reply-To: <49F065D6.1080300@theingots.org> References: <49F065D6.1080300@theingots.org> Message-ID: <200904231535.13258.daniel.is.fischer@web.de> Am Donnerstag 23 April 2009 14:57:58 schrieb Daniel Carrera: > Hi, > > I want to make a simple "average" function: > > average xs = (sum xs)/(length xs) > > When I try that on ghci I get the following error: > > No instance for (Fractional Int) > arising from a use of `/' at :1:17-36 > Possible fix: add an instance declaration for (Fractional Int) > In the expression: (sum xs) / (length xs) > In the definition of `average': average xs = (sum xs) / (length xs) > > Ok, so 'sum' is of type (Num a => [a] -> a), length is of type ([a] -> > Int) and (/) is of type (Fractional a => a -> a -> a). Can someone > explain how I can "add an instance declaration" to my function so as to > make all these types compatible? Don't. (you wouldn't add the instance declaration to the function, anyway, but to your module) Try explicitly converting the length to the appropriate type: average xs = sum xs / fromIntegral (length xs) will yield a working (albeit inefficient) average :: Fractional a => [a] -> a > > Thanks, > Daniel. From equaeghe at nospammail.net Thu Apr 23 09:45:27 2009 From: equaeghe at nospammail.net (Erik Quaeghebeur) Date: Thu Apr 23 09:31:52 2009 Subject: [Haskell-beginners] generating the set of all finite-valued functions on a finite space Message-ID: Hi, I'd like to lazily generate the set of all {-1,0,1}-valued functions on {'a','b','c'}? How should I best approach this. I was thinking about generalizing the power set definition powerset :: [a] -> [[a]] powerset = filterM (const [True, False]) but clearly don't know enough about filterM and the like to do it this way. Erik From daniel.carrera at theingots.org Thu Apr 23 09:52:00 2009 From: daniel.carrera at theingots.org (Daniel Carrera) Date: Thu Apr 23 09:38:08 2009 Subject: [Haskell-beginners] Help with types In-Reply-To: <200904231535.13258.daniel.is.fischer@web.de> References: <49F065D6.1080300@theingots.org> <200904231535.13258.daniel.is.fischer@web.de> Message-ID: <49F07280.4070603@theingots.org> Daniel Fischer wrote: > Try explicitly converting the length to the appropriate type: > > average xs = sum xs / fromIntegral (length xs) Thanks. Could you help me understand what's happening? 1. length returns Int. 2. sum returns Num. 3. (/) wants Fractional. It looks like (/) is happy with Num but doesn't like Int. This surprises me. I would have thought that Fractional is a kind of Num and Int is a kind of Fractional, so a function that expects Fractional would be happy with an Int but maybe not with a Num. But clearly that's not the way it works. 'fromIntegral' converts Int to Num. So obviously, Num is good and Int is bad. But I don't really get why. > will yield a working (albeit inefficient) > average :: Fractional a => [a] -> a Why is it inefficient? How would you make it efficient? Thanks for the help. Cheers, Daniel. From aditya.siram at gmail.com Thu Apr 23 09:55:51 2009 From: aditya.siram at gmail.com (aditya siram) Date: Thu Apr 23 09:41:53 2009 Subject: [Haskell-beginners] Help with types In-Reply-To: <49F07280.4070603@theingots.org> References: <49F065D6.1080300@theingots.org> <200904231535.13258.daniel.is.fischer@web.de> <49F07280.4070603@theingots.org> Message-ID: <594f78210904230655w52f8ad44k84a4e51b46eb25c1@mail.gmail.com> There is a chapter in Real World Haskell [1] devoted to this exact question on this exact piece of code. hth, -deech [1] http://book.realworldhaskell.org/read/profiling-and-optimization.html On Thu, Apr 23, 2009 at 8:52 AM, Daniel Carrera < daniel.carrera@theingots.org> wrote: > Daniel Fischer wrote: > >> Try explicitly converting the length to the appropriate type: >> >> average xs = sum xs / fromIntegral (length xs) >> > > Thanks. Could you help me understand what's happening? > > 1. length returns Int. > 2. sum returns Num. > 3. (/) wants Fractional. > > It looks like (/) is happy with Num but doesn't like Int. This surprises > me. I would have thought that Fractional is a kind of Num and Int is a kind > of Fractional, so a function that expects Fractional would be happy with an > Int but maybe not with a Num. But clearly that's not the way it works. > > 'fromIntegral' converts Int to Num. So obviously, Num is good and Int is > bad. But I don't really get why. > > > will yield a working (albeit inefficient) >> average :: Fractional a => [a] -> a >> > > Why is it inefficient? How would you make it efficient? > > Thanks for the help. > > Cheers, > > Daniel. > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090423/4ba489ef/attachment.htm From jason.dusek at gmail.com Thu Apr 23 10:08:10 2009 From: jason.dusek at gmail.com (Jason Dusek) Date: Thu Apr 23 09:54:12 2009 Subject: [Haskell-beginners] Help with types In-Reply-To: <49F07280.4070603@theingots.org> References: <49F065D6.1080300@theingots.org> <200904231535.13258.daniel.is.fischer@web.de> <49F07280.4070603@theingots.org> Message-ID: <42784f260904230708x40e4779g768c7afda9119e1@mail.gmail.com> 2009/04/23 Daniel Carrera : > It looks like (/) is happy with Num but doesn't like Int. This > surprises me. I would have thought that Fractional is a kind > of Num and Int is a kind of Fractional, so a function that > expects Fractional would be happy with an Int but maybe not > with a Num. But clearly that's not the way it works. In GHCi, let's have a look: Prelude> :info Int data Int = GHC.Types.I# GHC.Prim.Int# -- Defined in GHC.Types instance Bounded Int -- Defined in GHC.Enum instance Enum Int -- Defined in GHC.Enum instance Eq Int -- Defined in GHC.Base instance Integral Int -- Defined in GHC.Real instance Num Int -- Defined in GHC.Num instance Ord Int -- Defined in GHC.Base instance Read Int -- Defined in GHC.Read instance Real Int -- Defined in GHC.Real instance Show Int -- Defined in GHC.Show So `Int` is not actually a kind of `Fractional` (it's `Integral`, in fact). Prelude> :t (/) (/) :: forall a. (Fractional a) => a -> a -> a So `(/)` needs some `t` that is in `Fractional`. > 'fromIntegral' converts Int to Num. So obviously, Num is good and Int is > bad. But I don't really get why. Actually, `fromIntegral` takes any type `t` that is in `Integral` and makes it into some other type in `Num` as appropriate. You can use `fromIntegral` to go from `Int` to `Integer` or `Word32`, as well. To work with `(/)` we need a type that is in `Num` and in `Fractional`. The compiler defaults these *class constraints* to select, say `Double`. Then `fromIntegral` -- which can take any `Num` to any other `Num` -- does the "cast" from `Int` to `Double` for us. -- Jason Dusek From tom.davie at gmail.com Thu Apr 23 10:17:07 2009 From: tom.davie at gmail.com (Thomas Davie) Date: Thu Apr 23 10:03:12 2009 Subject: [Haskell-beginners] Help with types In-Reply-To: <49F07280.4070603@theingots.org> References: <49F065D6.1080300@theingots.org> <200904231535.13258.daniel.is.fischer@web.de> <49F07280.4070603@theingots.org> Message-ID: <3D95CE52-33BB-4F3A-B86D-14B12EA63341@gmail.com> On 23 Apr 2009, at 15:52, Daniel Carrera wrote: > Daniel Fischer wrote: >> Try explicitly converting the length to the appropriate type: >> average xs = sum xs / fromIntegral (length xs) > > Thanks. Could you help me understand what's happening? > > 1. length returns Int. > 2. sum returns Num. > 3. (/) wants Fractional. > > It looks like (/) is happy with Num but doesn't like Int. This > surprises me. I would have thought that Fractional is a kind of Num > and Int is a kind of Fractional Int isn't a Fractional because it can't represent fractional numbers. Bob From daniel.carrera at theingots.org Thu Apr 23 10:17:44 2009 From: daniel.carrera at theingots.org (Daniel Carrera) Date: Thu Apr 23 10:03:54 2009 Subject: [Haskell-beginners] Help with types In-Reply-To: <594f78210904230655w52f8ad44k84a4e51b46eb25c1@mail.gmail.com> References: <49F065D6.1080300@theingots.org> <200904231535.13258.daniel.is.fischer@web.de> <49F07280.4070603@theingots.org> <594f78210904230655w52f8ad44k84a4e51b46eb25c1@mail.gmail.com> Message-ID: <49F07888.1070108@theingots.org> aditya siram wrote: > There is a chapter in Real World Haskell [1] devoted to this exact > question on this exact piece of code. > > hth, > -deech > > [1] http://book.realworldhaskell.org/read/profiling-and-optimization.html Wow. Indeed, that is the exact same piece of code. Thanks. Daniel. From daniel.carrera at theingots.org Thu Apr 23 10:25:25 2009 From: daniel.carrera at theingots.org (Daniel Carrera) Date: Thu Apr 23 10:11:32 2009 Subject: [Haskell-beginners] Help with types In-Reply-To: <3D95CE52-33BB-4F3A-B86D-14B12EA63341@gmail.com> References: <49F065D6.1080300@theingots.org> <200904231535.13258.daniel.is.fischer@web.de> <49F07280.4070603@theingots.org> <3D95CE52-33BB-4F3A-B86D-14B12EA63341@gmail.com> Message-ID: <49F07A55.2020907@theingots.org> Thomas Davie wrote: >> It looks like (/) is happy with Num but doesn't like Int. This >> surprises me. I would have thought that Fractional is a kind of Num >> and Int is a kind of Fractional > > Int isn't a Fractional because it can't represent fractional numbers. Sure, but any integer is trivially also a fraction, so I would think that it would be an acceptable input for (/). On the other hand, if it is at all possible for a Num to contain something that cannot be converted to a fraction, then a Num should not be a valid input for (/). From jason.dusek at gmail.com Thu Apr 23 10:33:01 2009 From: jason.dusek at gmail.com (Jason Dusek) Date: Thu Apr 23 10:19:04 2009 Subject: [Haskell-beginners] Help with types In-Reply-To: <49F07A55.2020907@theingots.org> References: <49F065D6.1080300@theingots.org> <200904231535.13258.daniel.is.fischer@web.de> <49F07280.4070603@theingots.org> <3D95CE52-33BB-4F3A-B86D-14B12EA63341@gmail.com> <49F07A55.2020907@theingots.org> Message-ID: <42784f260904230733w6018bea8g30a5c555b8d8ecac@mail.gmail.com> 2009/04/23 Daniel Carrera : > ...if it is at all possible for a Num to contain something > that cannot be converted to a fraction, then a Num should not > be a valid input for (/). And it isn't. Prelude> :t (/) (/) :: forall a. (Fractional a) => a -> a -> a -- Jason Dusek From tom.davie at gmail.com Thu Apr 23 10:40:49 2009 From: tom.davie at gmail.com (Thomas Davie) Date: Thu Apr 23 10:26:55 2009 Subject: [Haskell-beginners] Help with types In-Reply-To: <49F07A55.2020907@theingots.org> References: <49F065D6.1080300@theingots.org> <200904231535.13258.daniel.is.fischer@web.de> <49F07280.4070603@theingots.org> <3D95CE52-33BB-4F3A-B86D-14B12EA63341@gmail.com> <49F07A55.2020907@theingots.org> Message-ID: On 23 Apr 2009, at 16:25, Daniel Carrera wrote: > Thomas Davie wrote: >>> It looks like (/) is happy with Num but doesn't like Int. This >>> surprises me. I would have thought that Fractional is a kind of >>> Num and Int is a kind of Fractional >> Int isn't a Fractional because it can't represent fractional numbers. > > Sure, but any integer is trivially also a fraction, so I would think > that it would be an acceptable input for (/). On the other hand, if > it is at all possible for a Num to contain something that cannot be > converted to a fraction, then a Num should not be a valid input for > (/). The problem here is that (/) also *outputs* that type ? if you can't represent a fraction, how do you give the result of 1/4? Bob From daniel.is.fischer at web.de Thu Apr 23 10:56:37 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Thu Apr 23 10:43:00 2009 Subject: [Haskell-beginners] Help with types In-Reply-To: <49F07280.4070603@theingots.org> References: <49F065D6.1080300@theingots.org> <200904231535.13258.daniel.is.fischer@web.de> <49F07280.4070603@theingots.org> Message-ID: <200904231656.38316.daniel.is.fischer@web.de> Am Donnerstag 23 April 2009 15:52:00 schrieb Daniel Carrera: > Daniel Fischer wrote: > > Try explicitly converting the length to the appropriate type: > > > > average xs = sum xs / fromIntegral (length xs) > > Thanks. Could you help me understand what's happening? > > 1. length returns Int. > 2. sum returns Num. > 3. (/) wants Fractional. > > It looks like (/) is happy with Num but doesn't like Int. Not quite. (/) needs a type which is an instance of Fractional. All instances of Fractional are also instances of Num, so Fractional is more specific than Num. If you divide the result of sum using (/), sum is used at the less general type (Fractional a => [a] -> a). Every function can be used at all types which are less general than its most general type. In this case it goes like this: The type checker sees average xs = sum xs / fromIntegral (length xs) so average is a function, having type arg -> result where xs :: arg sum xs / fromIntegral (length xs) :: result Now the right hand side, the expression sum xs / fromIntegral (length xs), is typed. (/) has the type Fractional a => a -> a -> a, so from that we can deduce that sum xs :: Fractional a => a fromIntegral (length xs) :: Fractional a => a result = Fractional a => a , all for the same a. sum has the type (Num n => [n] -> n), so for the expression sum xs to be well formed, xs must have the type (Num n => [n]), and then sum xs :: Num n => n Now that type has to be unified with the type deduced for this subexpression above. Since the first says whichever type, as long as it's a member of class Fractional and the second says whichever type, as long as it's a member of class Num, the unification yields "whichever type, as long as it's a member of both, class Fractional and class Num", (Fractional a, Num a) => a. Since Fractional is a subclass of Num, the second condition is implied by the first and the type simplifies to Fractional a => a. Since the type of xs' elements is th same as the type of sum xs, the Fractional constraint has to be added to the type of xs too, giving xs :: Fractional a => [a] arg = Fractional a => [a] fromIntegral has type (Integral a, Num b) => a -> b. Since length xs :: Int and Int is a member of Integral, fromIntegral (length xs) :: Num n => n This has to be unified with the type deduced above, giving fromIntegral (length xs) :: Fractional a => a , too. Note that (sum xs) and (fromIntegral (length xs)) have the type Fractional a => a *as subexpressions of sum xs / fromIntegral (length xs)*, in isolation, both would have the type Num n => n. Assembling all that, we find average :: Fractional a => [a] -> a > This surprises > me. I would have thought that Fractional is a kind of Num and Int is a > kind of Fractional, No, Int is an instance of Integral, which is sort of the opposite of Fractional. Fractional means that you can freely divide (excluding division by 0 of course), things like 3.24 make sense, Integral means that things like mod or gcd make sense. Though it is possible to make a type an instance of both, Fractional and Integral, that doesn't really make sense. > so a function that expects Fractional would be happy > with an Int but maybe not with a Num. But clearly that's not the way it > works. > > 'fromIntegral' converts Int to Num. So obviously, Num is good and Int is > bad. The thing is that the types are implicitly universally quantified, so the type of fromIntegral is really forall a b. (Integral a, Num b) => a -> b and the type of fromIntegral something is forall b. Num b => b > But I don't really get why. fromIntegral says, whatever Num type you want, I can give it to you. In particular, if the caller wants a Double, fromIntegral provides a Double. If the caller wants any type, as long as it's a member of Fractional, fromIntegral provides that. Int is a fixed type, the caller cannot choose which type shall be returned, it's always just Int, so the caller can only use operations which are defined on Int. (/) is not defined on Int, because the result of dividing two Ints is rarely an Int. For divisions of Integral types, there are div and quot (with mod and rem for the remainders). > > > will yield a working (albeit inefficient) > > average :: Fractional a => [a] -> a > > Why is it inefficient? How would you make it efficient? It's inefficient because the list has to be traversed twice, once for the sum and once for the length. Also, the whole list is kept in memory between the two traversals, which is a very bad thing for long lists. To make it efficient, calculate the sum and the length together, as in average xs = loop 0 0 xs where loop sm ln [] = sm / fromIntegral ln loop sm ln (y:ys) = loop (sm+y) (ln+1) ys although that probably needs strictness annotations on sm and ln to be efficient (otherwise, the running sum and length may not be evaluated but build up large thunks which are only forced at the end and may cause a stack overflow then). > > Thanks for the help. > > Cheers, > Daniel. From daniel.carrera at theingots.org Thu Apr 23 12:26:02 2009 From: daniel.carrera at theingots.org (Daniel Carrera) Date: Thu Apr 23 12:12:10 2009 Subject: [Haskell-beginners] Help with types In-Reply-To: <200904231656.38316.daniel.is.fischer@web.de> References: <49F065D6.1080300@theingots.org> <200904231535.13258.daniel.is.fischer@web.de> <49F07280.4070603@theingots.org> <200904231656.38316.daniel.is.fischer@web.de> Message-ID: <49F0969A.1090606@theingots.org> Daniel Fischer wrote: > Not quite. (/) needs a type which is an instance of Fractional. All instances of > Fractional are also instances of Num, so Fractional is more specific than Num. > If you divide the result of sum using (/), sum is used at the less general type > (Fractional a => [a] -> a). > Every function can be used at all types which are less general than its most > general type. Aahh.... I see. The "sum" part is making more sense now. So let's see: "sum" is a (Num a => [a] -> a). Every function can be used at all types that are less general than its most general type. Fractional is a kind of Num. Therefore, "sum" can be used as (Fractional a => [a] -> a) to make it compatible with (/). Thanks for the detailed explanation. It's a lot clearer now. >> This surprises >> me. I would have thought that Fractional is a kind of Num and Int is a >> kind of Fractional, > > No, Int is an instance of Integral, which is sort of the opposite of Fractional. > Fractional means that you can freely divide (excluding division by 0 of course), things > like 3.24 make sense, Integral means that things like mod or gcd make sense. > Though it is possible to make a type an instance of both, Fractional and Integral, that > doesn't really make sense. This helps. I think I see the problem: Suppose that Integral was a kind of Fractional, the way I proposed. What happens when someone writes (x / y) `mod` z ? Trying to apply the same reasoning you used above: (/) :: Fractional a => a -> a -> a mod :: Integral a => a -> a -> a Using the logic that you explained above, we would have to force (/) to give an Integral result, which in general is wrong. And that is a reasonable argument why Integral should not be an instance of Fractional. Am I right more or less? >> But I don't really get why. > > fromIntegral says, whatever Num type you want, I can give it to you. ... and 'length' says, "whatever Int type you want, I can give it to you", but (/) says "I don't want an Int, I want a Fractional" and that's why 'length' alone doesn't get along with (/). I'm beginning to see the reasoning behind Haskell's behaviour, but I think I'll need time to get used to it. Thanks for the help. Daniel. From marcot at holoscopio.com Thu Apr 23 13:15:05 2009 From: marcot at holoscopio.com (Marco =?ISO-8859-1?Q?T=FAlio?= Gontijo e Silva) Date: Thu Apr 23 13:01:35 2009 Subject: [Haskell-beginners] Type families with kind * -> * Message-ID: <1240506905.5271.60.camel@zezinho> Hello, I read the type families example at http://haskell.org/haskellwiki/GHC/Indexed_types and I wanted to do something similar to the Collects example, but using a type of kind * -> *: > class StateFunctor sf where > type SFMonad sf > type SFValue sf > sfmap :: (SFValue sf -> SFValue sf) -> sf -> SFMonad sf () I wrote the instance as: > instance StateFunctor (ListStore a) where > type SFMonad (ListStore a) = IO > type SFValue (ListStore a) = a > sfmap function listStore > = listStoreGetSize listStore >>= listStoreSfmap function listStore > listStoreSfmap :: (a -> a) -> ListStore a -> Int -> IO () > listStoreSfmap _function _listStore 0 = [] > listStoreSfmap function listStore size > = listStoreGetValue listStore index > >>= listStoreSetValue listStore index . function > >> listStoreSfmap function listStore index > where > index :: Int > index = pred size I'm getting: DistroCreator/GUI/List.hs:51:47: Kind error: `SFMonad' is applied to too many type arguments In the type `SFMonad sf ()' In the type `sf -> SFMonad sf ()' In the type `(SFValue sf -> SFValue sf) -> sf -> SFMonad sf ()' Failed, modules loaded: none. How can I use type families with types * -> *? Greetings. -- marcot http://marcot.iaaeee.org/ From jason.dusek at gmail.com Thu Apr 23 13:27:00 2009 From: jason.dusek at gmail.com (Jason Dusek) Date: Thu Apr 23 13:13:01 2009 Subject: [Haskell-beginners] Type families with kind * -> * In-Reply-To: <1240506905.5271.60.camel@zezinho> References: <1240506905.5271.60.camel@zezinho> Message-ID: <42784f260904231027y322bd884h184800d3d6aafc38@mail.gmail.com> class StateFunctor sf where ? type SFMonad sf :: * -> * ? type SFValue sf ? sfmap :: (SFValue sf -> SFValue sf) -> sf -> SFMonad sf () From daniel.is.fischer at web.de Thu Apr 23 13:32:15 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Thu Apr 23 13:18:38 2009 Subject: [Haskell-beginners] Type families with kind * -> * In-Reply-To: <1240506905.5271.60.camel@zezinho> References: <1240506905.5271.60.camel@zezinho> Message-ID: <200904231932.16242.daniel.is.fischer@web.de> Am Donnerstag 23 April 2009 19:15:05 schrieb Marco T?lio Gontijo e Silva: > Hello, > > I read the type families example at > http://haskell.org/haskellwiki/GHC/Indexed_types and I wanted to do > something similar to the Collects example, but using a type of kind * -> > > *: > > class StateFunctor sf where > > type SFMonad sf > > type SFValue sf > > sfmap :: (SFValue sf -> SFValue sf) -> sf -> SFMonad sf () > > I wrote the instance as: > > instance StateFunctor (ListStore a) where > > type SFMonad (ListStore a) = IO > > type SFValue (ListStore a) = a > > sfmap function listStore > > = listStoreGetSize listStore >>= listStoreSfmap function listStore > > > > listStoreSfmap :: (a -> a) -> ListStore a -> Int -> IO () > > listStoreSfmap _function _listStore 0 = [] > > listStoreSfmap function listStore size > > = listStoreGetValue listStore index > > > > >>= listStoreSetValue listStore index . function > > >> > > >> listStoreSfmap function listStore index > > > > where > > index :: Int > > index = pred size > > I'm getting: > > DistroCreator/GUI/List.hs:51:47: > Kind error: `SFMonad' is applied to too many type arguments > In the type `SFMonad sf ()' > In the type `sf -> SFMonad sf ()' > In the type `(SFValue sf -> SFValue sf) -> sf -> SFMonad sf ()' > Failed, modules loaded: none. > > How can I use type families with types * -> *? For example: ----------------------------------- {-# LANGUAGE TypeFamilies, KindSignatures #-} module TypeF where data ListStore a = Dummy listStoreGetSize = undefined listStoreSfmap = undefined class StateFunctor sf where ? type SFMonad sf :: (* -> *) ? type SFValue sf ? sfmap :: (SFValue sf -> SFValue sf) -> sf -> SFMonad sf () instance StateFunctor (ListStore a) where ? type SFMonad (ListStore a) = IO ? type SFValue (ListStore a) = a ? sfmap function listStore ? ? = listStoreGetSize listStore >>= listStoreSfmap function listStore ------------------------------------- Prelude> :l TypeF [1 of 1] Compiling TypeF ( TypeF.hs, interpreted ) Ok, modules loaded: TypeF. > > Greetings. From es at ertes.de Thu Apr 23 15:42:56 2009 From: es at ertes.de (Ertugrul Soeylemez) Date: Thu Apr 23 15:28:23 2009 Subject: [Haskell-beginners] Re: WWAAA... I hate monads References: <49EEEF9A.10307@theingots.org> <0DE0C1A3-4344-4AF1-AFBD-70A3F28A81CC@gmail.com> <49F03090.7070505@theingots.org> Message-ID: <20090423214256.7a107584@tritium.xx> Hello people, thanks for all your positive comments about my tutorial, both here and through direct email. I appreciate that very much. =) I'm glad that my work is helpful to the community. Greets, Ertugrul. Colin Paul Adams wrote: > >>>>> "Daniel" == Daniel Carrera writes: > > Daniel> Sam Martin wrote: > >>> This is excellent: > >>> > >>> http://ertes.de/articles/monads.html > >> > >> Wow. That really is a great tutorial! Suddenly the world > >> becomes clear... > >> > >> Definitely gets my vote as must read material. > > Daniel> +1 > > Daniel> I was very impressed too. And I am not easy to impress > Daniel> when it comes to documentation. I plan to read it a second > Daniel> time to solidify some of the ideas, but on my first > Daniel> reading my understanding of Monads increased by leaps and > Daniel> bounds. > > Daniel> Ertugrul deserves to be commended, and this tutorial > Daniel> should be made more prominent on haskell.org. > > I think so. > I've read VERY MANY tutorials on monads, and they were all confusing - > except this one. -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://blog.ertes.de/ From equaeghe at nospammail.net Thu Apr 23 17:54:15 2009 From: equaeghe at nospammail.net (Erik Quaeghebeur) Date: Thu Apr 23 17:40:18 2009 Subject: [Haskell-beginners] problem cabal install'ing hmatrix In-Reply-To: <49F02B30.8090000@um.es> References: <49ED7A6A.5090103@um.es> <49F02B30.8090000@um.es> Message-ID: >> Original message: >> > > >> > > $ cabal install hmatrix >> > > Resolving dependencies... >> > > Configuring hmatrix-0.5.1.1... >> > > Preprocessing library hmatrix-0.5.1.1... >> > > running dist/build/Numeric/GSL/Special/Internal_hsc_make failed >> > > command was: dist/build/Numeric/GSL/Special/Internal_hsc_make >> > > > dist/build/Numeric/GSL/Special/Internal.hs >> > > cabal: Error: some packages failed to install: >> > > hmatrix-0.5.1.1 failed during the building phase. The exception was: >> > > exit: ExitFailure 1 >> > > >> > > What should I do to diagnose/resolve this problem? On Thu, 23 Apr 2009, Alberto Ruiz wrote: > > Probably a dependency not mentionend in extra-libraries is missing. There is > not a standard way to link -llapack. For instance, in Ubuntu/Debian we only > need gsl and lapack: > > $ ld -lgsl -llapack > ld: warning: cannot find entry symbol _start; not setting start address > > This means that everything is ok, but in other systems we may also need some > of -l[gsl]cblas, -lgfortran, or -lf77blas, -latlas, -lgcc_s, etc. > > Try to find the correct libraries with > > $ ld -lgsl -llapack -lgslcblas # ld -lgsl -llapack -lgslcblas ld: warning: cannot find entry symbol _start; not setting start address > or other combinations, and modify the extra-libraries field in hmatrix.cabal. > In any case, I will try to add cabal flags to cover common situations. (There > is also a possible issue with ghc-6.8 that must be fixed, but the library > should work ok with 6.10). # ghc --version The Glorious Glasgow Haskell Compilation System, version 6.8.2 It seems we still don't know the cause; any more things I can do to diagnose? I'll also investigate the possibilities of resolving this issue by using the gentoo haskell overlay or non-stable versions of ghc (6.10) in Gentoo's repository. Erik From equaeghe at nospammail.net Thu Apr 23 18:16:06 2009 From: equaeghe at nospammail.net (Erik Quaeghebeur) Date: Thu Apr 23 18:02:11 2009 Subject: [Haskell-beginners] generating the set of all finite-valued ... In-Reply-To: <20090423160017.GA29444@lxultra2.macs.hw.ac.uk> References: <20090423160017.GA29444@lxultra2.macs.hw.ac.uk> Message-ID: > On Thu, Apr 23, 2009 at 03:45:27PM +0200, Erik Quaeghebeur wrote: >> >> I'd like to lazily generate the set of all {-1,0,1}-valued functions on >> {'a','b','c'}? How should I best approach this. I was thinking about >> generalizing the power set definition On Thu, 23 Apr 2009, Jan Jakubuv wrote: > > Try to start with this: > > mapM (\x -> [(x,-1),(x,0),(x,1)]) ['a','b','c'] Aha. Great. Thanks, Jan. And now I realized that I don't really care about the domain, so I said: Prelude> let m = mapM (\x -> [(x,-1),(x,0),(x,1)]) ['a','b','c'] Prelude> map (\x -> snd $ unzip x) m [[-1,-1,-1],[-1,-1,0],[-1,-1,1],[-1,0,-1],[-1,0,0],[-1,0,1],[-1,1,-1],[-1,1,0],[-1,1,1],[0,-1,-1],[0,-1,0],[0,-1,1],[0,0,-1],[0,0,0],[0,0,1],[0,1,-1],[0,1,0],[0,1,1],[1,-1,-1],[1,-1,0],[1,-1,1],[1,0,-1],[1,0,0],[1,0,1],[1,1,-1],[1,1,0],[1,1,1]] Any more direct way of doing this? (Still trying to understand how the mapM works... I've found it's sequence.map, but that doesn't really help.) The next step will be to choose a good data format for what I'm trying to achieve. The functions (now represented as lists) would more naturally be represented as column matrices, e.g., from Numeric.LinearAlgebra of hmatrix, as I'll be needing some linear system solver. I can do the transition from lists to that, but I'm afraid they don't give me the necessary flexibility; I'd need to filter them based on (maximum/minimum) component values and sum them and such. Any thoughts on that? Erik From es at ertes.de Thu Apr 23 18:56:50 2009 From: es at ertes.de (Ertugrul Soeylemez) Date: Thu Apr 23 18:42:18 2009 Subject: [Haskell-beginners] Re: computation vs function References: <49EF8036.7020503@theingots.org> <20090423011028.1724247c@tritium.xx> <49F035B9.8090502@theingots.org> Message-ID: <20090424005650.3741ea91@tritium.xx> Daniel Carrera wrote: > > What I refer to as a 'computation' in the article is actually just a > > value of type 'Monad m => m a'. I have chosen that term, because > > you can apply it to any monad I've seen. As mentioned in section 5, > > you can think of 'Just 3' as being a computation, which results in > > 3. But it's important that this is not a function, but just an > > independent value. > > Thanks. > > I think the article would benefit from making the meaning of > computation clearer. The word computation appears in the tutorial 51 > times before section 5. That means that when I tried to go back for a > definition of computation I couldn't find one. > > The first place you use the word computation is in the preamble, but > that's not a good place to define terms. The second time you use the > word computation is in section 2 "Motivation". This might be a good > place to define the term. The Motivation section already defines > several terms (referentially transparent, purely functional, etc), so > it seems like a good place to define computation as well. > > In section 2 we can't say "Monad => m a" or "Just 3" because the terms > are not introduced yet. Perhaps you could say something like this: > > > The word 'computation' here is not a technical term. I use it to refer > to something that returns a value without taking in any > parameters. For example (m a) is a computation that takes no > parameters but returns a value of type 'a' whereas (a -> b) is a > function that takes a parameter of type 'a' and returns a value of > type 'b'. It is important that a computation is not a function, but an > independent value. > > > I think that adding that as the third paragraph in the Motivation > section would be helpful. In addition, in the Preamble, when you use > the word computation, I would add "(see next section)". Yes, you're right about that and I'm going to restructure it a bit, when I've got some time. But I can't do much more than clarifying that the term is just an intuition and that it shouldn't be confused with functions, maybe writing a bit more about the difference between the two. This is precisely the reason why I mentioned Brent's blog post [1]. He hit the nail right on the head. I think a monads tutorial is supposed to be read twice. > Question: Would it be reasonable to say that a computation is a > wrapper? I'm not sure, because I don't know if a computation always > results in the *same* value (you know, side-effects). I know that > "Just 3" always results in 3, but is that universal? Don't confuse the concept of a computation with the concept of running it. A computation does not result at all, unless you have a notion of running it. That notion defines what it means for a computation to "result". An IO computation can give different results in each run, a Maybe computation can't. I'm giving a few examples to make this clearer: * IO: Running an IO computation is possible through running the program. There is no safe notion of running a computation from Haskell. This is intentional, as you can see in more detail in the tutorial. * Parser: Running a Parser computation is possible through parsing a text. The result is the outcome of that process. * State s: Running a 'State s'-computation means calling the underlying function, which implements the stateful computation, with an initial state value. * Maybe and []: Running a Maybe or list computation is extracting its value through support functions (fromJust, maybe, head, tail, etc.) or through pattern matching. Replace "wrapper" by "container", then you have another intuition for monadic values. An IO container contains some value, which depends on world state, the Maybe container contains some value or not, the list container contains arbitrarily many values, the Parser container contains the outcome of parsing something, etc. All in all, a monad is a wrapper type, but it doesn't exactly wrap values. There is an interesting counter-example, the unit monad: data Unit a = Unit Think of it as a Maybe monad, which is constrained to Nothing. There is no result of the computation, there is no value in the container, there is no whatever in the burrito. Nonetheless Unit is a perfectly valid monad and here is its instance: instance Monad Unit where return = const Unit _ >>= _ = Unit Greets, Ertugrul. -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://blog.ertes.de/ From aruiz at um.es Fri Apr 24 05:23:10 2009 From: aruiz at um.es (Alberto Ruiz) Date: Fri Apr 24 05:09:15 2009 Subject: [Haskell-beginners] problem cabal install'ing hmatrix In-Reply-To: References: <49ED7A6A.5090103@um.es> <49F02B30.8090000@um.es> Message-ID: <49F184FE.6040404@um.es> Erik, if you get > # ld -lgsl -llapack -lgslcblas > ld: warning: cannot find entry symbol _start; not setting start address perhaps you only need to uncomment line 141 in hmatrix.cabal and try "cabal install" in that folder. This is not the default because we prefer to link with a possibly optimized cblas. Clearly hmatrix requires a previous configure step. Alberto Erik Quaeghebeur wrote: >>> Original message: >>> > > > > $ cabal install hmatrix >>> > > Resolving dependencies... >>> > > Configuring hmatrix-0.5.1.1... >>> > > Preprocessing library hmatrix-0.5.1.1... >>> > > running dist/build/Numeric/GSL/Special/Internal_hsc_make failed >>> > > command was: dist/build/Numeric/GSL/Special/Internal_hsc_make >>> > > > dist/build/Numeric/GSL/Special/Internal.hs >>> > > cabal: Error: some packages failed to install: >>> > > hmatrix-0.5.1.1 failed during the building phase. The exception >>> was: >>> > > exit: ExitFailure 1 >>> > > > > What should I do to diagnose/resolve this problem? > > On Thu, 23 Apr 2009, Alberto Ruiz wrote: >> >> Probably a dependency not mentionend in extra-libraries is missing. >> There is not a standard way to link -llapack. For instance, in >> Ubuntu/Debian we only need gsl and lapack: >> >> $ ld -lgsl -llapack >> ld: warning: cannot find entry symbol _start; not setting start address >> >> This means that everything is ok, but in other systems we may also >> need some of -l[gsl]cblas, -lgfortran, or -lf77blas, -latlas, -lgcc_s, >> etc. >> >> Try to find the correct libraries with >> >> $ ld -lgsl -llapack -lgslcblas > > # ld -lgsl -llapack -lgslcblas > ld: warning: cannot find entry symbol _start; not setting start address > >> or other combinations, and modify the extra-libraries field in >> hmatrix.cabal. In any case, I will try to add cabal flags to cover >> common situations. (There is also a possible issue with ghc-6.8 that >> must be fixed, but the library should work ok with 6.10). > > # ghc --version > The Glorious Glasgow Haskell Compilation System, version 6.8.2 > > > It seems we still don't know the cause; any more things I can do to > diagnose? > > I'll also investigate the possibilities of resolving this issue by using > the gentoo haskell overlay or non-stable versions of ghc (6.10) in > Gentoo's repository. > > Erik > From j.romildo at gmail.com Fri Apr 24 06:11:53 2009 From: j.romildo at gmail.com (j.romildo@gmail.com) Date: Fri Apr 24 05:59:00 2009 Subject: [Haskell-beginners] Re: WWAAA... I hate monads In-Reply-To: <20090423214256.7a107584@tritium.xx> References: <49EEEF9A.10307@theingots.org> <0DE0C1A3-4344-4AF1-AFBD-70A3F28A81CC@gmail.com> <49F03090.7070505@theingots.org> <20090423214256.7a107584@tritium.xx> Message-ID: <20090424101153.GA13514@darling.DHCP-GERAL> On Thu, Apr 23, 2009 at 09:42:56PM +0200, Ertugrul Soeylemez wrote: > Hello people, > > thanks for all your positive comments about my tutorial, both here and > through direct email. I appreciate that very much. =) > > I'm glad that my work is helpful to the community. Would you provide a PDF version along with the HTML version? Regards, Romildo > Colin Paul Adams wrote: > > > >>>>> "Daniel" == Daniel Carrera writes: > > > > Daniel> Sam Martin wrote: > > >>> This is excellent: > > >>> > > >>> http://ertes.de/articles/monads.html > > >> > > >> Wow. That really is a great tutorial! Suddenly the world > > >> becomes clear... > > >> > > >> Definitely gets my vote as must read material. > > > > Daniel> +1 > > > > Daniel> I was very impressed too. And I am not easy to impress > > Daniel> when it comes to documentation. I plan to read it a second > > Daniel> time to solidify some of the ideas, but on my first > > Daniel> reading my understanding of Monads increased by leaps and > > Daniel> bounds. > > > > Daniel> Ertugrul deserves to be commended, and this tutorial > > Daniel> should be made more prominent on haskell.org. > > > > I think so. > > I've read VERY MANY tutorials on monads, and they were all confusing - > > except this one. From jakubuv at gmail.com Fri Apr 24 06:36:44 2009 From: jakubuv at gmail.com (Jan Jakubuv) Date: Fri Apr 24 06:23:08 2009 Subject: [Haskell-beginners] generating the set of all finite-valued ... In-Reply-To: References: <20090423160017.GA29444@lxultra2.macs.hw.ac.uk> Message-ID: <20090424103644.GA28584@lxultra2.macs.hw.ac.uk> On Fri, Apr 24, 2009 at 12:16:06AM +0200, Erik Quaeghebeur wrote: > > Aha. Great. Thanks, Jan. And now I realized that I don't really care > about the domain, so I said: > > Prelude> let m = mapM (\x -> [(x,-1),(x,0),(x,1)]) ['a','b','c'] > Prelude> map (\x -> snd $ unzip x) m > [[-1,-1,-1],[-1,-1,0],[-1,-1,1],[-1,0,-1],[-1,0,0],[-1,0,1],[-1,1,-1],[-1,1,0],[-1,1,1],[0,-1,-1],[0,-1,0],[0,-1,1],[0,0,-1],[0,0,0],[0,0,1],[0,1,-1],[0,1,0],[0,1,1],[1,-1,-1],[1,-1,0],[1,-1,1],[1,0,-1],[1,0,0],[1,0,1],[1,1,-1],[1,1,0],[1,1,1]] > > Any more direct way of doing this? (Still trying to understand how the > mapM works... I've found it's sequence.map, but that doesn't really > help.) > Well, you can write: mapM (const [-1,0,1]) [1..3] mapM takes a function which returns a computation for a given argument. In this case the function always returns the computation [-1,0,1] which you can think of as a non-deterministic computation resulting in either -1, or 0, or 1. This computation is executed for every value in the list [1..3] and because this list has three values the execution results in [x,y,z] where each of x, y, and z is either -1, or 0, or -1. This gives you all variations. You can also write: [[x,y,z] | x<-[-1,0,1], y<-[-1,0,1], z<-[-1,0,1]] Sincerely, Jan. -- Heriot-Watt University is a Scottish charity registered under charity number SC000278. From byorgey at seas.upenn.edu Fri Apr 24 09:24:00 2009 From: byorgey at seas.upenn.edu (Brent Yorgey) Date: Fri Apr 24 09:10:00 2009 Subject: [Haskell-beginners] generating the set of all finite-valued ... In-Reply-To: <20090424103644.GA28584@lxultra2.macs.hw.ac.uk> References: <20090423160017.GA29444@lxultra2.macs.hw.ac.uk> <20090424103644.GA28584@lxultra2.macs.hw.ac.uk> Message-ID: <20090424132400.GA17979@seas.upenn.edu> On Fri, Apr 24, 2009 at 11:36:44AM +0100, Jan Jakubuv wrote: > On Fri, Apr 24, 2009 at 12:16:06AM +0200, Erik Quaeghebeur wrote: > > > > Aha. Great. Thanks, Jan. And now I realized that I don't really care > > about the domain, so I said: > > > > Prelude> let m = mapM (\x -> [(x,-1),(x,0),(x,1)]) ['a','b','c'] > > Prelude> map (\x -> snd $ unzip x) m > > [[-1,-1,-1],[-1,-1,0],[-1,-1,1],[-1,0,-1],[-1,0,0],[-1,0,1],[-1,1,-1],[-1,1,0],[-1,1,1],[0,-1,-1],[0,-1,0],[0,-1,1],[0,0,-1],[0,0,0],[0,0,1],[0,1,-1],[0,1,0],[0,1,1],[1,-1,-1],[1,-1,0],[1,-1,1],[1,0,-1],[1,0,0],[1,0,1],[1,1,-1],[1,1,0],[1,1,1]] > > > > Any more direct way of doing this? (Still trying to understand how the > > mapM works... I've found it's sequence.map, but that doesn't really > > help.) > > > > Well, you can write: > > mapM (const [-1,0,1]) [1..3] Better yet (in my opinion), you can just write sequence (replicate 3 [-1,0,1]) which is really the same thing, since mapM = sequence . map. Mapping (const [-1,0,1]) over [1..3] yields [[-1,0,1], [-1,0,1], [-1,0,1]], that is, (replicate 3 [-1,0,1]). It's the 'sequence' that does the magic of selecting an item from each of the three lists in all possible ways. -Brent From es at ertes.de Fri Apr 24 10:18:01 2009 From: es at ertes.de (Ertugrul Soeylemez) Date: Fri Apr 24 10:03:21 2009 Subject: [Haskell-beginners] Re: WWAAA... I hate monads References: <49EEEF9A.10307@theingots.org> <0DE0C1A3-4344-4AF1-AFBD-70A3F28A81CC@gmail.com> <49F03090.7070505@theingots.org> <20090423214256.7a107584@tritium.xx> <20090424101153.GA13514@darling.DHCP-GERAL> Message-ID: <20090424161801.067f2fcf@tritium.xx> j.romildo@gmail.com wrote: > > thanks for all your positive comments about my tutorial, both here > > and through direct email. I appreciate that very much. =) > > > > I'm glad that my work is helpful to the community. > > Would you provide a PDF version along with the HTML version? That will require me to write another XSLT stylesheet, something which I was going to do anyway, but haven't done yet. If you would like to convert it yourself, you'll find the original source files here: * http://ertes.de/articles/monads.xml * http://ertes.de/articles/Article.xsl * http://ertes.de/articles/Article.rng Greets, Ertugrul. -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://blog.ertes.de/ From fbrubacher at gmail.com Fri Apr 24 10:37:10 2009 From: fbrubacher at gmail.com (Federico Brubacher) Date: Fri Apr 24 10:23:10 2009 Subject: [Haskell-beginners] Re: WWAAA... I hate monads In-Reply-To: <20090424161801.067f2fcf@tritium.xx> References: <49EEEF9A.10307@theingots.org> <0DE0C1A3-4344-4AF1-AFBD-70A3F28A81CC@gmail.com> <49F03090.7070505@theingots.org> <20090423214256.7a107584@tritium.xx> <20090424101153.GA13514@darling.DHCP-GERAL> <20090424161801.067f2fcf@tritium.xx> Message-ID: <206c53410904240737u71c93904j53cd11195a38b03c@mail.gmail.com> While i agree to some extent that analogies are bad in some sense , i found this one really insightful when i was trying to put my head around monads : http://www.haroldtherebel.com/2007/12/02/monads-and-schroedingers-cat/ what do u guys think ? On Fri, Apr 24, 2009 at 11:18 AM, Ertugrul Soeylemez wrote: > j.romildo@gmail.com wrote: > > > > thanks for all your positive comments about my tutorial, both here > > > and through direct email. I appreciate that very much. =) > > > > > > I'm glad that my work is helpful to the community. > > > > Would you provide a PDF version along with the HTML version? > > That will require me to write another XSLT stylesheet, something which I > was going to do anyway, but haven't done yet. If you would like to > convert it yourself, you'll find the original source files here: > > * http://ertes.de/articles/monads.xml > * http://ertes.de/articles/Article.xsl > * http://ertes.de/articles/Article.rng > > > Greets, > Ertugrul. > > > -- > nightmare = unsafePerformIO (getWrongWife >>= sex) > http://blog.ertes.de/ > > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -- Federico Brubacher www.fbrubacher.com Colonial Duty Free Shop www.colonial.com.uy -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090424/8b0b91e8/attachment.htm From michael at snoyman.com Fri Apr 24 10:53:22 2009 From: michael at snoyman.com (Michael Snoyman) Date: Fri Apr 24 10:39:22 2009 Subject: [Haskell-beginners] Re: WWAAA... I hate monads In-Reply-To: <206c53410904240737u71c93904j53cd11195a38b03c@mail.gmail.com> References: <49EEEF9A.10307@theingots.org> <0DE0C1A3-4344-4AF1-AFBD-70A3F28A81CC@gmail.com> <49F03090.7070505@theingots.org> <20090423214256.7a107584@tritium.xx> <20090424101153.GA13514@darling.DHCP-GERAL> <20090424161801.067f2fcf@tritium.xx> <206c53410904240737u71c93904j53cd11195a38b03c@mail.gmail.com> Message-ID: <29bf512f0904240753g738b13a0oa3143d181affd4a4@mail.gmail.com> On Fri, Apr 24, 2009 at 5:37 PM, Federico Brubacher wrote: > While i agree to some extent that analogies are bad in some sense , i found > this one really insightful when i was trying to put my head around monads : > http://www.haroldtherebel.com/2007/12/02/monads-and-schroedingers-cat/ > > what do u guys think ? > I could be wrong here, but isn't he really describing functors and not monads? Michael -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090424/eba83a38/attachment.htm From byorgey at seas.upenn.edu Fri Apr 24 11:11:44 2009 From: byorgey at seas.upenn.edu (Brent Yorgey) Date: Fri Apr 24 10:57:44 2009 Subject: [Haskell-beginners] Re: WWAAA... I hate monads In-Reply-To: <29bf512f0904240753g738b13a0oa3143d181affd4a4@mail.gmail.com> References: <0DE0C1A3-4344-4AF1-AFBD-70A3F28A81CC@gmail.com> <49F03090.7070505@theingots.org> <20090423214256.7a107584@tritium.xx> <20090424101153.GA13514@darling.DHCP-GERAL> <20090424161801.067f2fcf@tritium.xx> <206c53410904240737u71c93904j53cd11195a38b03c@mail.gmail.com> <29bf512f0904240753g738b13a0oa3143d181affd4a4@mail.gmail.com> Message-ID: <20090424151144.GA24277@seas.upenn.edu> On Fri, Apr 24, 2009 at 05:53:22PM +0300, Michael Snoyman wrote: > On Fri, Apr 24, 2009 at 5:37 PM, Federico Brubacher wrote: > > > While i agree to some extent that analogies are bad in some sense , i found > > this one really insightful when i was trying to put my head around monads : > > http://www.haroldtherebel.com/2007/12/02/monads-and-schroedingers-cat/ > > > > what do u guys think ? > > > > I could be wrong here, but isn't he really describing functors and not > monads? Well, it isn't quite clear, because the explanation seems sort of confused. The "monads are a box that you can keep stuff in but can't get stuff out of" metaphor is not new (google "monad space suit") and in my opinion is somewhat unhelpful, for several reasons: (1) with many monads, you CAN "get stuff out of the box"; but how you do so is specific to each monad. (2) As pointed out by Michael, the explanation in the linked blog post seems to conflate fmap and (>>=), or at least glosses over the difference. But this is a very crucial difference that you must understand to manipulate anything more concrete than imaginary boxes containing cats. -Brent From daniel.carrera at theingots.org Fri Apr 24 12:09:40 2009 From: daniel.carrera at theingots.org (Daniel Carrera) Date: Fri Apr 24 11:55:45 2009 Subject: [Haskell-beginners] Re: WWAAA... I hate monads In-Reply-To: <206c53410904240737u71c93904j53cd11195a38b03c@mail.gmail.com> References: <49EEEF9A.10307@theingots.org> <0DE0C1A3-4344-4AF1-AFBD-70A3F28A81CC@gmail.com> <49F03090.7070505@theingots.org> <20090423214256.7a107584@tritium.xx> <20090424101153.GA13514@darling.DHCP-GERAL> <20090424161801.067f2fcf@tritium.xx> <206c53410904240737u71c93904j53cd11195a38b03c@mail.gmail.com> Message-ID: <49F1E444.4080505@theingots.org> Federico Brubacher wrote: > While i agree to some extent that analogies are bad in some sense , i > found this one really insightful when i was trying to put my head around > monads : > > http://www.haroldtherebel.com/2007/12/02/monads-and-schroedingers-cat/ > > what do u guys think ? Personally, I don't find this analogy useful. Because monads are obviously not Schr?dinger's cat, the analogy makes me feel like I don't actually have any idea of what monads are. There are other things that I thought were more confusing than useful: If you have a monad (m a) you do not "put a function (a -> b) into the box". First of all, the second parameter of the bind operator does not have the signature (a -> b). It has the signature (a -> m b). Another problem with saying box or wrapper, which Ertugrul pointed out when I said "wrapper" is that the monad may not always return the same result. To quote Ertugrul: "An IO computation can give different results in each run". Finally, the analogy with Schr?dinger doesn't seem apt. The point of Schr?dinger's cat is that he is simultaneously dead and alive until you open the box to make a measurement. This is not how monads behave. It is *not* a property of Schr?dinger's cat that you can't interact with the cat. Sure you can, just make a measurement. Finally, this page doesn't have all the detailed explanation that is necessary to make an analogy really work. Daniel. From equaeghe at nospammail.net Fri Apr 24 12:20:30 2009 From: equaeghe at nospammail.net (Erik Quaeghebeur) Date: Fri Apr 24 12:06:53 2009 Subject: [Haskell-beginners] generating the set of all finite-valued ... In-Reply-To: <20090424132400.GA17979@seas.upenn.edu> References: <20090423160017.GA29444@lxultra2.macs.hw.ac.uk> <20090424103644.GA28584@lxultra2.macs.hw.ac.uk> <20090424132400.GA17979@seas.upenn.edu> Message-ID: >> On Fri, Apr 24, 2009 at 12:16:06AM +0200, Erik Quaeghebeur wrote: >>> >>> m = mapM (\x -> [(x,-1),(x,0),(x,1)]) ['a','b','c'] >>> map (\x -> snd $ unzip x) m >>> >>> Any more direct way of doing this? > On Fri, Apr 24, 2009 at 11:36:44AM +0100, Jan Jakubuv wrote: >> >> Well, you can write: >> >> mapM (const [-1,0,1]) [1..3] On Fri, 24 Apr 2009, Brent Yorgey wrote: > > Better yet (in my opinion), you can just write > > sequence (replicate 3 [-1,0,1]) > > which is really the same thing, since mapM = sequence . map. Mapping > (const [-1,0,1]) over [1..3] yields [[-1,0,1], [-1,0,1], [-1,0,1]], > that is, (replicate 3 [-1,0,1]). It's the 'sequence' that does the > magic of selecting an item from each of the three lists in all > possible ways. Yes, now I see it, thanks to both Jan and Brent. I can nicely generalize this to n = ... values = [...] sequence (replicate n values) My ideas about how I should approach other aspects of my programming task are also crystallizing. Now find a nice stretch of time to work things out... Erik From es at ertes.de Fri Apr 24 13:19:41 2009 From: es at ertes.de (Ertugrul Soeylemez) Date: Fri Apr 24 13:05:02 2009 Subject: [Haskell-beginners] Re: WWAAA... I hate monads References: <49EEEF9A.10307@theingots.org> <0DE0C1A3-4344-4AF1-AFBD-70A3F28A81CC@gmail.com> <49F03090.7070505@theingots.org> <20090423214256.7a107584@tritium.xx> <20090424101153.GA13514@darling.DHCP-GERAL> <20090424161801.067f2fcf@tritium.xx> <206c53410904240737u71c93904j53cd11195a38b03c@mail.gmail.com> <49F1E444.4080505@theingots.org> Message-ID: <20090424191941.0a274c8e@tritium.xx> Daniel Carrera wrote: > > While i agree to some extent that analogies are bad in some sense , > > i found this one really insightful when i was trying to put my head > > around monads : > > > > http://www.haroldtherebel.com/2007/12/02/monads-and-schroedingers-cat/ > > > > what do u guys think ? > > Personally, I don't find this analogy useful. Because monads are > obviously not Schr?dinger's cat, the analogy makes me feel like I > don't actually have any idea of what monads are. > > There are other things that I thought were more confusing than useful: > If you have a monad (m a) you do not "put a function (a -> b) into the > box". First of all, the second parameter of the bind operator does not > have the signature (a -> b). It has the signature (a -> m b). I think, this is rather an allusion to functors. > Another problem with saying box or wrapper, which Ertugrul pointed out > when I said "wrapper" is that the monad may not always return the same > result. To quote Ertugrul: "An IO computation can give different > results in each run". Monadic values (computations, containers, whatever you call them) are expressed intrinsically without a notion of running them. Running is something separate and specific to particular monads. There may be monads, which are not supposed to be "run", or for which "running" doesn't make any sense at all. > Finally, the analogy with Schr?dinger doesn't seem apt. The point of > Schr?dinger's cat is that he is simultaneously dead and alive until > you open the box to make a measurement. This is not how monads > behave. It is *not* a property of Schr?dinger's cat that you can't > interact with the cat. Sure you can, just make a measurement. Actually Schr?dinger's cat is neither dead nor alive. Its state S is a unit vector living in a Hilbert space. The two possible measurement outcomes are also unit vectors in that vector space. They form an orthonormal basis, but S isn't equal to either of them. Measuring S means turning it into one of them, thereby destroying the original state. Greets, Ertugrul. -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://blog.ertes.de/ From flopticalogic at gmail.com Fri Apr 24 15:07:28 2009 From: flopticalogic at gmail.com (Floptical Logic) Date: Fri Apr 24 14:53:27 2009 Subject: [Haskell-beginners] doing state right In-Reply-To: References: Message-ID: Bah! I completely forgot arrays were constant in lookup. Thanks On Thu, Apr 23, 2009 at 3:05 AM, Chadda? Fouch? wrote: > On Thu, Apr 23, 2009 at 10:03 AM, Chadda? Fouch? > wrote: >> >> main = quick_ppm "foo.ppm" (\i j -> isPrime ((i-1)*limit+j)) limit limit >> ?where >> ? ?isPrime n = primeSieve ! n >> ? ?primeSieve :: UArray Int Bool >> ? ?primeSieve = accumArray (\_ _ -> True) False (0,limit*limit) $ zip >> primes (repeat ()) >> > > That should read as "zip (takeWhile (<= limit*limit) primes) (repeat > ())" of course. > > -- > Jeda? > From daniel.carrera at theingots.org Fri Apr 24 16:50:28 2009 From: daniel.carrera at theingots.org (Daniel Carrera) Date: Fri Apr 24 16:36:31 2009 Subject: [Haskell-beginners] Re: WWAAA... I hate monads In-Reply-To: <20090424191941.0a274c8e@tritium.xx> References: <49EEEF9A.10307@theingots.org> <0DE0C1A3-4344-4AF1-AFBD-70A3F28A81CC@gmail.com> <49F03090.7070505@theingots.org> <20090423214256.7a107584@tritium.xx> <20090424101153.GA13514@darling.DHCP-GERAL> <20090424161801.067f2fcf@tritium.xx> <206c53410904240737u71c93904j53cd11195a38b03c@mail.gmail.com> <49F1E444.4080505@theingots.org> <20090424191941.0a274c8e@tritium.xx> Message-ID: <49F22614.5010809@theingots.org> Ertugrul Soeylemez wrote: > Actually Schr?dinger's cat is neither dead nor alive. Its state S is a > unit vector living in a Hilbert space. I spoke imprecisely, but I do know about superposition. I took a couple of quantum courses when I got my physics degree (but generally I focused on astrophysics which is far more interesting than quantum mechanics). Daniel. From walck at lvc.edu Fri Apr 24 22:31:29 2009 From: walck at lvc.edu (Walck, Scott) Date: Fri Apr 24 22:17:29 2009 Subject: [Haskell-beginners] parser comparison question Message-ID: I've been comparing Graham Hutton's simple parser with Parsec. Here is some example code. -- Comparison of Hutton's simple parser with Parsec -- Hutton's simple parser is available at -- http://www.cs.nott.ac.uk/~gmh/Parsing.lhs -- Hutton simple parser called H -- Parsec called P import qualified Parsing as H import qualified Text.ParserCombinators.Parsec as P exH = H.parse (H.string "hi") "hiho" exP = P.parse (P.string "hi") "" "hiho" charH = H.parse (H.char 'a' H.+++ H.char 'b') "bbb" charP = P.parse (P.char 'a' P.<|> P.char 'b') "" "bbb" choiceH = H.parse (H.string "hoo" H.+++ H.string "ho") "hono" choiceP1 = P.parse (P.string "bb" P.<|> P.string "ba") "" "bbb" choiceP2 = P.parse (P.string "ba" P.<|> P.string "bb") "" "bbb" choiceP22 = P.parse (P.try (P.string "ba") P.<|> P.string "bb") "" "bbc" I am interested if anyone could comment on the design of the Parsec 'try' function. For example, choiceP2 fails and returns Left error, while choiceP22 succeeds. Hutton's simple parser doesn't need try. It seems so simple and elegant. I'm wondering why Parsec requires me to use 'try' for a string parse that might fail. Thanks, Scott Scott N. Walck Associate Professor of Physics Lebanon Valley College From joel.neely at gmail.com Fri Apr 24 23:17:35 2009 From: joel.neely at gmail.com (Joel Neely) Date: Fri Apr 24 23:03:34 2009 Subject: [Haskell-beginners] Re: WWAAA... I hate monads In-Reply-To: <20090424101153.GA13514@darling.DHCP-GERAL> References: <49EEEF9A.10307@theingots.org> <0DE0C1A3-4344-4AF1-AFBD-70A3F28A81CC@gmail.com> <49F03090.7070505@theingots.org> <20090423214256.7a107584@tritium.xx> <20090424101153.GA13514@darling.DHCP-GERAL> Message-ID: <5e0b968a0904242017v6c7d6c0cq35855361321ee278@mail.gmail.com> With Ertugrul's permission, I've done a simple print-to-PDF of his "Understanding Haskell Monads" tutorial, and am providing the PDF file to this list. -jn- On Fri, Apr 24, 2009 at 5:11 AM, wrote: > On Thu, Apr 23, 2009 at 09:42:56PM +0200, Ertugrul Soeylemez wrote: >> Hello people, >> >> thanks for all your positive comments about my tutorial, both here and >> through direct email. ?I appreciate that very much. =) >> >> I'm glad that my work is helpful to the community. > > Would you provide a PDF version along with the HTML version? > > Regards, > > Romildo > >> Colin Paul Adams wrote: >> >> > >>>>> "Daniel" == Daniel Carrera writes: >> > >> > ? ? Daniel> Sam Martin wrote: >> > ? ? >>> This is excellent: >> > ? ? >>> >> > ? ? >>> http://ertes.de/articles/monads.html >> > ? ? >> >> > ? ? >> Wow. That really is a great tutorial! Suddenly the world >> > ? ? >> becomes clear... >> > ? ? >> >> > ? ? >> Definitely gets my vote as must read material. >> > >> > ? ? Daniel> +1 >> > >> > ? ? Daniel> I was very impressed too. And I am not easy to impress >> > ? ? Daniel> when it comes to documentation. I plan to read it a second >> > ? ? Daniel> time to solidify some of the ideas, but on my first >> > ? ? Daniel> reading my understanding of Monads increased by leaps and >> > ? ? Daniel> bounds. >> > >> > ? ? Daniel> Ertugrul deserves to be commended, and this tutorial >> > ? ? Daniel> should be made more prominent on haskell.org. >> > >> > I think so. >> > I've read VERY MANY tutorials on monads, and they were all confusing - >> > except this one. > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -- Beauty of style and harmony and grace and good rhythm depend on simplicity. - Plato -------------- next part -------------- A non-text attachment was scrubbed... Name: Understanding Haskell Monads.pdf Type: application/pdf Size: 257719 bytes Desc: not available Url : http://www.haskell.org/pipermail/beginners/attachments/20090424/5476cc76/UnderstandingHaskellMonads-0001.pdf From es at ertes.de Sat Apr 25 03:35:09 2009 From: es at ertes.de (Ertugrul Soeylemez) Date: Sat Apr 25 03:20:25 2009 Subject: [Haskell-beginners] Re: WWAAA... I hate monads References: <49EEEF9A.10307@theingots.org> <0DE0C1A3-4344-4AF1-AFBD-70A3F28A81CC@gmail.com> <49F03090.7070505@theingots.org> <20090423214256.7a107584@tritium.xx> <20090424101153.GA13514@darling.DHCP-GERAL> <20090424161801.067f2fcf@tritium.xx> <206c53410904240737u71c93904j53cd11195a38b03c@mail.gmail.com> <49F1E444.4080505@theingots.org> <20090424191941.0a274c8e@tritium.xx> <49F22614.5010809@theingots.org> Message-ID: <20090425093509.7d6fd088@tritium.xx> Daniel Carrera wrote: > > Actually Schr?dinger's cat is neither dead nor alive. Its state S > > is a unit vector living in a Hilbert space. > > I spoke imprecisely, but I do know about superposition. I took a > couple of quantum courses when I got my physics degree (but generally > I focused on astrophysics which is far more interesting than quantum > mechanics). I just wanted to justify why the cat is neither dead nor alive, not both at the same time, as seems to be the common sense about quantum mechanics. But of course, this is totally off topic here. =) Greets, Ertugrul. -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://blog.ertes.de/ From daniel.is.fischer at web.de Sat Apr 25 04:34:29 2009 From: daniel.is.fischer at web.de (Daniel Fischer) Date: Sat Apr 25 04:20:54 2009 Subject: [Haskell-beginners] parser comparison question In-Reply-To: References: Message-ID: <200904251034.30159.daniel.is.fischer@web.de> Am Samstag 25 April 2009 04:31:29 schrieb Walck, Scott: > I've been comparing Graham Hutton's simple parser with Parsec. Here is > some example code. > > -- Comparison of Hutton's simple parser with Parsec > > -- Hutton's simple parser is available at > -- http://www.cs.nott.ac.uk/~gmh/Parsing.lhs > > -- Hutton simple parser called H > -- Parsec called P > > import qualified Parsing as H > import qualified Text.ParserCombinators.Parsec as P > > exH = H.parse (H.string "hi") "hiho" > exP = P.parse (P.string "hi") "" "hiho" > > charH = H.parse (H.char 'a' H.+++ H.char 'b') "bbb" > charP = P.parse (P.char 'a' P.<|> P.char 'b') "" "bbb" > > choiceH = H.parse (H.string "hoo" H.+++ H.string "ho") "hono" > choiceP1 = P.parse (P.string "bb" P.<|> P.string "ba") "" "bbb" > choiceP2 = P.parse (P.string "ba" P.<|> P.string "bb") "" "bbb" > > choiceP22 = P.parse (P.try (P.string "ba") P.<|> P.string "bb") "" "bbc" > > I am interested if anyone could comment on the design of the Parsec 'try' > function. For example, choiceP2 fails and returns Left error, while > choiceP22 succeeds. > > Hutton's simple parser doesn't need try. It seems so simple and elegant. > I'm wondering why Parsec requires me to use 'try' for a string parse that > might fail. In short: efficiency The simple parser is a fully backtracking parser, therefore it has to keep the whole input available in case a parse fails and an alternative has to be tried. Parsec's alternative (<|>) tries the second parser only if the first parser failed *without consuming any input*, so the input consumed so far can be immediately discarded, which is more efficient. To get backtracking behaviour you must wrap the first parser in a 'try', which makes it either succeed or fail without consuming any input. Using try means keeping more of the input available, which has a performance cost, so use try sparingly, try to write your parsers so that they either succeed or fail (almost) immediately (P.try (P.string "ba") requires only a short part of the input kept available, so it doesn't hurt performance measurably, but imagine you have a parser that can fail after having consumed 500MB of input. Keeping that around to try the second alternative on as the simple parser must do will hurt.) > > Thanks, > > Scott > > > Scott N. Walck > Associate Professor of Physics > Lebanon Valley College > From mpm at alumni.caltech.edu Sat Apr 25 19:39:44 2009 From: mpm at alumni.caltech.edu (Michael Mossey) Date: Sat Apr 25 19:26:00 2009 Subject: [Haskell-beginners] music layout problem Message-ID: <49F39F40.7010501@alumni.caltech.edu> I'm continuing to work on this music layout problem, and I'm trying another angle. A page of music is made of many individual symbols and graphical items like lines and arcs. I decided to call a drawable symbol/item a Grapheme. so type MusicPage = [Grapheme] The program also maintains the more fundamental description of music in conceptual form---that is, notes, chords, time signatures, tempo indications, etc. I decided to call bits of information about music Datemes. type MusicScore = [Dateme] A function to lay out a musical page would have this signature: layoutPage :: [Dateme] -> [Grapheme] Now let's think about the structure of a page of music for a moment. It's made of *systems*, which are groups of notes read from left to right. A page consists of a number of systems stacked vertically (like a page of text has lines of text stacked vertically). The layout algorithm will fit as many systems as it can into a page. When it runs out of space, it will stop (even if there are Dateme left). A layout algorithm in imperative pseudocode would look something like: - initialize the list remainingDateme to the input list of Dateme - loop - looking at the list of remainingDateme, make a system - try to fit the system to the page - if the system doesn't fit, break out of the loop - add the system to the page - drop the used Dateme from remainingDateme - if remainingDateme is empty, break out of the loop - go to top of loop I tried to write this in Haskell, and it seem awkward. It would be something like: -- layout page, produce list of Grapheme and also list of -- unused Dateme layoutPage :: PageDimensions -> [Dateme] -> ( [Grapheme], [Dateme] ) layoutPage dim dateme = layoutPage' dim [] dateme layoutPage' :: PageDimensions -> [Grapheme] -> [Dateme] -> ( [Grapheme], [Dateme] ) layoutPage' dim graphemeSoFar [] = ( graphemeSoFar, [] ) layoutPage' dim graphemeSoFar remainingDateme = let ( newGrapheme, remainingDateme', dim' ) = layoutSystem dim remainingDateme in if null newGrapheme then ( graphemeSoFar, remainingDateme ) else layoutPage' dim' (graphemeSoFar ++ newGrapheme) remainingDateme' We assume this is defined elsewhere: -- layoutSystem takes as input the current page dimensions (think of -- the "current page dimensions" as the room *remaining* on the page), -- and a list of Dateme, and returns the triple: -- ( [Grapheme] for the new system, or null list if no additional system -- can fit on the page, -- remaining [Dateme] that are not consumed, -- new page dimensions ) layoutSystem :: PageDimensions -> [Dateme] -> ( [Grapheme], [Dateme], PageDimensions ) From apfelmus at quantentunnel.de Mon Apr 27 13:34:33 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Mon Apr 27 13:20:31 2009 Subject: [Haskell-beginners] Sequence for functors that are not applicative? In-Reply-To: References: <49EB97F4.9090906@alumni.caltech.edu> <49EBBD82.7050300@alumni.caltech.edu> Message-ID: Hello, I would like to write a function convert :: [(Name, [(Time, Chord)])] -> [(Time, [(Name, Chord)])] which transposes a finite map [(Name,b)] of event lists [(Time,a)] into an event list of finite maps. Sterling remarked that this looks very much like a job for sequence , but since event lists are not even applicative functors, I wonder whether an abstraction with less requirements can be found. Below is a first try. Heinrich Apfelmus wrote: > Sterling Clover wrote: >> Maybe just bikeshedding here (and on -beginners, no less), but this >> seems like a job for Data.Traversable.sequence? >> >> sequence :: Monad m => t (m a) -> m (t a) >> > > Great idea! > > My type signature is wrong, it should actually read > > convert :: [Named [Timed Chord]] -> [Timed [Named Chord]] > > I'm not sure whether sequence applies directly, > > type EventList a = [Timed a] > > is not a monad. It's not quite an applicative functor either, because in > > (<*>) :: EventList (a -> b) -> EventList a -> EventList b > > it's not clear what should happen to events from the left and right list > that are not simultaneous. This needs further thought. It appears that type EventList a = [(Time, a)] -- ascending times is not an applicative functor, but only a "monoid preserving functor" instance Monoid a => Monoid (EventList a) where mempty = [] mappend xs ys = map mconcat . groupBy ((==) `on` fst) . sortBy (comparing fst) (xs ++ ys) The same is true for type Group a = [(Name, a)] instance Monoid a => Monoid (Group a) where ... Put differently, we have two functions unionWith :: (a -> a -> a) -> EventList a -> EventList a -> EventList a unionWith :: (a -> a -> a) -> Group a -> Group a -> Group a Additionally, we need concat :: (a -> a -> a) -> Group a -> a and a strange function cobind' :: Functor f => Group (f a) -> Group (f (Group a)) cobind' xs = [(name, fmap (\y -> (name,y)) x) | (name,x) <- xs] that is reminiscent of a comonad. With this machinery, we can write convert :: Group (EventList a) -> EventList (Group a) convert = concat (unionWith (unionWith snd)) . cobind' No idea whether all this is overkill. After all, convert is but a glorified transpose. Regards, apfelmus -- http://apfelmus.nfshost.com From equaeghe at nospammail.net Mon Apr 27 14:39:26 2009 From: equaeghe at nospammail.net (Erik Quaeghebeur) Date: Mon Apr 27 14:25:21 2009 Subject: [Haskell-beginners] generating the set of all finite-valued [...] In-Reply-To: <3678e0bb0904262229w6102deaanb646638bd29dac1f@mail.gmail.com> References: <3678e0bb0904262229w6102deaanb646638bd29dac1f@mail.gmail.com> Message-ID: > 2009/4/23 Erik Quaeghebeur > >> I'd like to lazily generate the set of all {-1,0,1}-valued functions on >> {'a','b','c'}? How should I best approach this. I was thinking about >> generalizing the power set definition >> >> powerset :: [a] -> [[a]] >> powerset = filterM (const [True, False]) >> >> but clearly don't know enough about filterM and the like to do it this way. >> >> Erik On Mon, 27 Apr 2009, Haroldo Stenger wrote: > > i got curious about this one. Can you elaborate ? Well, elaborate about my ultimate goal, or about the powerset definition? The latter I can tell little about, I found it on-line and recognized it as a starting point. The former: generalizing http://users.ugent.be/~equaeghe/constraints.php to previsions from probabilities; C++ is a little too heavy, so I thought I'd try out Haskell. Erik From equaeghe at nospammail.net Mon Apr 27 18:05:38 2009 From: equaeghe at nospammail.net (Erik Quaeghebeur) Date: Mon Apr 27 17:51:37 2009 Subject: [Haskell-beginners] problem cabal install'ing hmatrix In-Reply-To: <49F184FE.6040404@um.es> References: <49ED7A6A.5090103@um.es> <49F02B30.8090000@um.es> <49F184FE.6040404@um.es> Message-ID: On Fri, 24 Apr 2009, Alberto Ruiz wrote: > > Erik, if you get > >> # ld -lgsl -llapack -lgslcblas >> ld: warning: cannot find entry symbol _start; not setting start address > > perhaps you only need to uncomment line 141 in hmatrix.cabal and try "cabal > install" in that folder. > > This is not the default because we prefer to link with a possibly optimized > cblas. Clearly hmatrix requires a previous configure step. I've managed to get things working using the gentoo haskell overlay! I had an optimized blas installed (atlas), but perhaps it wasn't automatically detected? Anyhow, it works now; there is no need to get deeper into the distribution-specific behavior. I can focus on coding. Erik From aditya.siram at gmail.com Tue Apr 28 01:43:36 2009 From: aditya.siram at gmail.com (aditya siram) Date: Tue Apr 28 01:29:38 2009 Subject: [Haskell-beginners] Working With TVars Message-ID: <594f78210904272243q69118d73w1d02b869f3468337@mail.gmail.com> Hi all, I have a tuple inside a TVar : > type MySTM = TVar (Int,Int) Whenever I want to edit/read 'a' or 'b' I find myself writing : > editFunction mySTM = do (a',b') <- readTVar mySTM dostuff a' ... This is boilerplate stuff, so I decided to write some accessors. So far I have : > getA , getB :: MySTM -> STM Int > getA mySTM = do > (a',b') <- readTVar mySTM > return a' > > getB mySTM = do > (a',b') <- readTVar mySTM > return b' I want to be able to use these accessors like so: > doSomethingWithA mySTM = do > case (getA mySTM) of > 1 -> doStuff > 0 -> doSomethingElse But getA returns an STM Int, so I still have to do a : > doSomethingWithA = do > a' <- (getA mySTM) > case a' of > 1 -> doStuff > 0 -> doSomethingElse This doesn't really save me a lot of boilerplate. What is the best way of writing a function that just returns my values do I can work with them in the STM monad without unpacking them all the time? Thanks , Deech -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090428/4d57a761/attachment.htm From chaddai.fouche at gmail.com Tue Apr 28 03:26:18 2009 From: chaddai.fouche at gmail.com (=?UTF-8?B?Q2hhZGRhw68gRm91Y2jDqQ==?=) Date: Tue Apr 28 03:12:34 2009 Subject: [Haskell-beginners] generating the set of all finite-valued ... In-Reply-To: References: <20090423160017.GA29444@lxultra2.macs.hw.ac.uk> <20090424103644.GA28584@lxultra2.macs.hw.ac.uk> <20090424132400.GA17979@seas.upenn.edu> Message-ID: On Fri, Apr 24, 2009 at 6:20 PM, Erik Quaeghebeur wrote: > Yes, now I see it, thanks to both Jan and Brent. > I can nicely generalize this to > > ? ? ? ?n = ... > ? ? ? ?values = [...] > ? ? ? ?sequence (replicate n values) > (sequence (replicate n xs)) is part of Control.Monad under the name replicateM so : > replicateM n values -- Jeda? From byorgey at seas.upenn.edu Tue Apr 28 08:41:13 2009 From: byorgey at seas.upenn.edu (Brent Yorgey) Date: Tue Apr 28 08:27:05 2009 Subject: [Haskell-beginners] Working With TVars In-Reply-To: <594f78210904272243q69118d73w1d02b869f3468337@mail.gmail.com> References: <594f78210904272243q69118d73w1d02b869f3468337@mail.gmail.com> Message-ID: <20090428124113.GA28976@seas.upenn.edu> > > But getA returns an STM Int, so I still have to do a : > > doSomethingWithA = do > > a' <- (getA mySTM) > > case a' of > > 1 -> doStuff > > 0 -> doSomethingElse > > This doesn't really save me a lot of boilerplate. What is the best way of > writing a function that just returns my values do I can work with them in > the STM monad without unpacking them all the time? You can't; that is the whole point. However, there are ways to save some typing. For example, you could use (>>=), which the do-notation desugars to anyway: doSomethingWithA = getA mySTM >>= \a' -> case a' of ... In this case, that doesn't actually save that much, I guess. But you could go much further. For example, if you often find yourself doing case analysis on the value of a, you could write something like caseA :: STM e -> STM e -> STM e caseA act1 act2 = do a' <- (getA mySTM) case a' of 1 -> act1 0 -> act2 Then you could just write 'caseA doStuff doSomethingElse'. And if you wanted something more general than just matching on 1 or 0, you could write (say) caseA' :: [(Int, STM e)] -> STM e And so on. The trick is to abstract out the common patterns in your code. Haskell is really good at this---if you find yourself typing the same boilerplate over and over again, there's (often) a way to abstract out the commonality. -Brent From aditya.siram at gmail.com Tue Apr 28 11:49:26 2009 From: aditya.siram at gmail.com (aditya siram) Date: Tue Apr 28 11:35:17 2009 Subject: [Haskell-beginners] Problem install ghc 6.10.2 Message-ID: <594f78210904280849y58e0d1a6la6afa8d0da0eab2f@mail.gmail.com> Hi all, I am trying to install the Linux GHC 6.10.2 binary, but when I fire up ghci I get the following error: GHCi, version 6.10.2: http://www.haskell.org/ghc/ :? for help Glasgow Haskell Compiler, Version 6.10.2, for Haskell 98, stage 2 booted by GHC version 6.10.1 Using package config file: /usr/local/lib/ghc-6.10.2/./package.conf wired-in package ghc-prim[""] not found. wired-in package integer[""] not found. wired-in package base[""] not found. wired-in package rts mapped to rts-1.0 wired-in package haskell98[""] not found. wired-in package syb[""] not found. wired-in package template-haskell[""] not found. wired-in package dph-seq[""] not found. wired-in package dph-par[""] not found. package haddock-2.4.2 will be ignored due to missing or recursive dependencies: Cabal-1.6.0.3 array-0.2.0.0 base-4.1.0.0 containers-0.2.0.1 directory-1.0.0.3 filepath-1.1.0.2 ghc-6.10.2 haskell98-1.0.1.0 pretty-1.0.1.0 package ghc-6.10.2 will be ignored due to missing or recursive dependencies: Cabal-1.6.0.3 array-0.2.0.0 base-4.1.0.0 bytestring-0.9.1.4 containers-0.2.0.1 directory-1.0.0.3 editline-0.2.1.0 filepath-1.1.0.2 haskell98-1.0.1.0 hpc-0.5.0.3 old-time-1.0.0.2 process-1.0.1.1 template-haskell-2.3.0.1 unix-2.3.2.0 Hsc static flags: -static *** Deleting temp files: Deleting: *** Deleting temp dirs: Deleting: ghc: panic! (the 'impossible' happened) (GHC version 6.10.2 for i386-unknown-linux): interactiveUI:setBuffering2 Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug Running ghc-pkg check gave me : There are problems in package haddock-2.4.2: dependency Cabal-1.6.0.3 doesn't exist dependency array-0.2.0.0 doesn't exist dependency base-4.1.0.0 doesn't exist dependency containers-0.2.0.1 doesn't exist dependency directory-1.0.0.3 doesn't exist dependency filepath-1.1.0.2 doesn't exist dependency haskell98-1.0.1.0 doesn't exist dependency pretty-1.0.1.0 doesn't exist There are problems in package ghc-6.10.2: dependency Cabal-1.6.0.3 doesn't exist dependency array-0.2.0.0 doesn't exist dependency base-4.1.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency containers-0.2.0.1 doesn't exist dependency directory-1.0.0.3 doesn't exist dependency editline-0.2.1.0 doesn't exist dependency filepath-1.1.0.2 doesn't exist dependency haskell98-1.0.1.0 doesn't exist dependency hpc-0.5.0.3 doesn't exist dependency old-time-1.0.0.2 doesn't exist dependency process-1.0.1.1 doesn't exist dependency template-haskell-2.3.0.1 doesn't exist dependency unix-2.3.2.0 doesn't exist The following packages are broken, either because they have a problem listed above, or because they depend on a broken package. haddock-2.4.2 ghc-6.10.2 Listing user packages ( ghc-pkg list --user ) shows that ghc-pkg is looking for a package.conf in ~/.ghc/i386-linux-6.10.2/package.conf which doesn't exist:. So I created it and copied over the package.conf file from ~/.ghc/i386-linux-6.10.1/ and ran ghc-pkg check again with the following error : There are problems in package CC-delcont-0.2: dependency base-3.0.3.0 doesn't exist dependency mtl-1.1.0.2 doesn't exist There are problems in package terminfo-0.2.2.1: dependency base-3.0.3.0 doesn't exist There are problems in package darcs-2.2.0: dependency array-0.2.0.0 doesn't exist dependency base-3.0.3.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency filepath-1.1.0.1 doesn't exist dependency html-1.0.1.2 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency parsec-2.1.0.1 doesn't exist dependency process-1.0.1.0 doesn't exist dependency random-1.0.0.1 doesn't exist dependency regex-compat-0.71.0.1 doesn't exist dependency unix-2.3.1.0 doesn't exist There are problems in package extensible-exceptions-0.1.1.0: dependency base-4.0.0.0 doesn't exist There are problems in package binary-0.4.4: dependency array-0.2.0.0 doesn't exist dependency base-3.0.3.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency containers-0.2.0.0 doesn't exist There are problems in package syb-with-class-0.4: dependency array-0.2.0.0 doesn't exist dependency base-3.0.3.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency template-haskell-2.3.0.0 doesn't exist There are problems in package hspread-0.3.1: dependency base-3.0.3.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency containers-0.2.0.0 doesn't exist There are problems in package happstack-state-0.1: dependency base-4.0.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency filepath-1.1.0.1 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency random-1.0.0.1 doesn't exist dependency stm-2.1.1.2 doesn't exist dependency syb-0.1.0.0 doesn't exist dependency template-haskell-2.3.0.0 doesn't exist dependency unix-2.3.1.0 doesn't exist There are problems in package happstack-ixset-0.1: dependency base-4.0.0.0 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency syb-0.1.0.0 doesn't exist dependency template-haskell-2.3.0.0 doesn't exist There are problems in package happstack-server-0.1: dependency base-4.0.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency html-1.0.1.2 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-locale-1.0.0.1 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency parsec-2.1.0.1 doesn't exist dependency process-1.0.1.0 doesn't exist dependency syb-0.1.0.0 doesn't exist dependency template-haskell-2.3.0.0 doesn't exist dependency unix-2.3.1.0 doesn't exist dependency xhtml-3000.2.0.1 doesn't exist There are problems in package happstack-contrib-0.1: dependency base-4.0.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency syb-0.1.0.0 doesn't exist dependency unix-2.3.1.0 doesn't exist There are problems in package X11-1.4.5: dependency base-3.0.3.0 doesn't exist There are problems in package xmonad-0.8.1: dependency base-3.0.3.0 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency process-1.0.1.0 doesn't exist dependency unix-2.3.1.0 doesn't exist There are problems in package utf8-string-0.3.4: dependency base-3.0.3.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist There are problems in package X11-xft-0.3: dependency base-3.0.3.0 doesn't exist There are problems in package ghc-paths-0.1.0.5: dependency base-3.0.3.0 doesn't exist There are problems in package haddock-2.4.1: dependency Cabal-1.6.0.1 doesn't exist dependency array-0.2.0.0 doesn't exist dependency base-4.0.0.0 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency filepath-1.1.0.1 doesn't exist dependency ghc-6.10.1 doesn't exist dependency pretty-1.0.1.0 doesn't exist There are problems in package regex-base-0.93.1: dependency array-0.2.0.0 doesn't exist dependency base-3.0.3.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency mtl-1.1.0.2 doesn't exist There are problems in package regex-posix-0.94.1: dependency array-0.2.0.0 doesn't exist dependency base-3.0.3.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency containers-0.2.0.0 doesn't exist There are problems in package regex-compat-0.92: dependency array-0.2.0.0 doesn't exist dependency base-3.0.3.0 doesn't exist There are problems in package syb-with-class-0.5.1: dependency array-0.2.0.0 doesn't exist dependency base-3.0.3.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency template-haskell-2.3.0.0 doesn't exist There are problems in package terminfo-0.3: dependency base-3.0.3.0 doesn't exist There are problems in package time-1.1.2.3: dependency base-3.0.3.0 doesn't exist dependency old-locale-1.0.0.1 doesn't exist There are problems in package xmonad-contrib-0.8.1: dependency base-3.0.3.0 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-locale-1.0.0.1 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency process-1.0.1.0 doesn't exist dependency random-1.0.0.1 doesn't exist dependency unix-2.3.1.0 doesn't exist There are problems in package wxcore-0.11.0: dependency base-4.0.0.0 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency stm-2.1.1.2 doesn't exist There are problems in package process-1.0.1.1: dependency base-4.0.0.0 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency filepath-1.1.0.1 doesn't exist dependency unix-2.3.1.0 doesn't exist There are problems in package darcs-2.2.1: dependency array-0.2.0.0 doesn't exist dependency base-3.0.3.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency filepath-1.1.0.1 doesn't exist dependency html-1.0.1.2 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency parsec-2.1.0.1 doesn't exist dependency random-1.0.0.1 doesn't exist dependency unix-2.3.1.0 doesn't exist There are problems in package haskell98-1.0.1.0: dependency array-0.2.0.0 doesn't exist dependency base-4.0.0.0 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency old-locale-1.0.0.1 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency random-1.0.0.1 doesn't exist There are problems in package HaXml-1.13.3: dependency base-3.0.3.0 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency pretty-1.0.1.0 doesn't exist There are problems in package terminfo-0.3.0.1: dependency base-3.0.3.0 doesn't exist There are problems in package hslogger-1.0.7: dependency base-3.0.3.0 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-locale-1.0.0.1 doesn't exist dependency unix-2.3.1.0 doesn't exist There are problems in package happstack-util-0.1: dependency HUnit-1.2.0.3 doesn't exist dependency QuickCheck-1.2.0.0 doesn't exist dependency array-0.2.0.0 doesn't exist dependency base-4.0.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency random-1.0.0.1 doesn't exist dependency template-haskell-2.3.0.0 doesn't exist There are problems in package happstack-data-0.1: dependency base-4.0.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency pretty-1.0.1.0 doesn't exist dependency syb-0.1.0.0 doesn't exist dependency template-haskell-2.3.0.0 doesn't exist There are problems in package happstack-util-0.1.9: dependency HUnit-1.2.0.3 doesn't exist dependency QuickCheck-1.2.0.0 doesn't exist dependency array-0.2.0.0 doesn't exist dependency base-4.0.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency random-1.0.0.1 doesn't exist dependency template-haskell-2.3.0.0 doesn't exist There are problems in package happstack-data-0.1.9: dependency HUnit-1.2.0.3 doesn't exist dependency base-4.0.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency pretty-1.0.1.0 doesn't exist dependency syb-0.1.0.0 doesn't exist dependency template-haskell-2.3.0.0 doesn't exist There are problems in package happstack-state-0.1.9: dependency HUnit-1.2.0.3 doesn't exist dependency base-4.0.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency filepath-1.1.0.1 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency random-1.0.0.1 doesn't exist dependency stm-2.1.1.2 doesn't exist dependency syb-0.1.0.0 doesn't exist dependency template-haskell-2.3.0.0 doesn't exist dependency unix-2.3.1.0 doesn't exist There are problems in package happstack-ixset-0.1.9: dependency HUnit-1.2.0.3 doesn't exist dependency base-4.0.0.0 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency syb-0.1.0.0 doesn't exist dependency template-haskell-2.3.0.0 doesn't exist There are problems in package MaybeT-0.1.2: dependency base-3.0.3.0 doesn't exist dependency mtl-1.1.0.2 doesn't exist There are problems in package zlib-0.5.0.0: dependency base-3.0.3.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist There are problems in package happstack-server-0.1.9: dependency HUnit-1.2.0.3 doesn't exist dependency base-4.0.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency html-1.0.1.2 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-locale-1.0.0.1 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency parsec-2.1.0.1 doesn't exist dependency syb-0.1.0.0 doesn't exist dependency template-haskell-2.3.0.0 doesn't exist dependency unix-2.3.1.0 doesn't exist dependency xhtml-3000.2.0.1 doesn't exist There are problems in package happstack-contrib-0.1.9: dependency HUnit-1.2.0.3 doesn't exist dependency base-4.0.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency syb-0.1.0.0 doesn't exist dependency unix-2.3.1.0 doesn't exist There are problems in package HJavaScript-0.4.4: dependency base-3.0.3.0 doesn't exist There are problems in package cpphs-1.6: dependency base-3.0.3.0 doesn't exist There are problems in package harp-0.4: dependency base-3.0.3.0 doesn't exist There are problems in package haskell-src-exts-0.4.8: dependency array-0.2.0.0 doesn't exist dependency base-4.0.0.0 doesn't exist dependency pretty-1.0.1.0 doesn't exist There are problems in package hsx-0.4.8: dependency base-3.0.3.0 doesn't exist dependency mtl-1.1.0.2 doesn't exist There are problems in package HJScript-0.4.4: dependency base-3.0.3.0 doesn't exist dependency mtl-1.1.0.2 doesn't exist There are problems in package hsp-0.4.5: dependency base-3.0.3.0 doesn't exist dependency mtl-1.1.0.2 doesn't exist There are problems in package happstack-0.1.9: dependency base-4.0.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency filepath-1.1.0.1 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency syb-0.1.0.0 doesn't exist There are problems in package Xauth-0.1: dependency base-3.0.3.0 doesn't exist There are problems in package byteorder-1.0.0: dependency base-3.0.3.0 doesn't exist There are problems in package xhb-0.2.2009.2.21: dependency base-3.0.3.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency parsec-2.1.0.1 doesn't exist dependency stm-2.1.1.2 doesn't exist There are problems in package HStringTemplate-0.4.3: dependency array-0.2.0.0 doesn't exist dependency base-3.0.3.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency filepath-1.1.0.1 doesn't exist dependency old-locale-1.0.0.1 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency parsec-2.1.0.1 doesn't exist dependency pretty-1.0.1.0 doesn't exist There are problems in package happstack-util-0.2.1: dependency HUnit-1.2.0.3 doesn't exist dependency QuickCheck-1.2.0.0 doesn't exist dependency array-0.2.0.0 doesn't exist dependency base-4.0.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-locale-1.0.0.1 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency parsec-2.1.0.1 doesn't exist dependency random-1.0.0.1 doesn't exist dependency template-haskell-2.3.0.0 doesn't exist There are problems in package happstack-data-0.2.1: dependency HUnit-1.2.0.3 doesn't exist dependency base-4.0.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency pretty-1.0.1.0 doesn't exist dependency syb-0.1.0.0 doesn't exist dependency template-haskell-2.3.0.0 doesn't exist There are problems in package happstack-ixset-0.2.1: dependency HUnit-1.2.0.3 doesn't exist dependency base-4.0.0.0 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency syb-0.1.0.0 doesn't exist dependency template-haskell-2.3.0.0 doesn't exist There are problems in package happstack-server-0.2.1: dependency HUnit-1.2.0.3 doesn't exist dependency base-4.0.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency html-1.0.1.2 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-locale-1.0.0.1 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency parsec-2.1.0.1 doesn't exist dependency syb-0.1.0.0 doesn't exist dependency template-haskell-2.3.0.0 doesn't exist dependency unix-2.3.1.0 doesn't exist dependency xhtml-3000.2.0.1 doesn't exist There are problems in package happstack-state-0.2.1: dependency HUnit-1.2.0.3 doesn't exist dependency base-4.0.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency filepath-1.1.0.1 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency random-1.0.0.1 doesn't exist dependency stm-2.1.1.2 doesn't exist dependency syb-0.1.0.0 doesn't exist dependency template-haskell-2.3.0.0 doesn't exist dependency unix-2.3.1.0 doesn't exist There are problems in package happstack-0.2.1: dependency HUnit-1.2.0.3 doesn't exist dependency base-4.0.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency filepath-1.1.0.1 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency syb-0.1.0.0 doesn't exist There are problems in package uniplate-1.2.0.3: dependency base-4.0.0.0 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency syb-0.1.0.0 doesn't exist There are problems in package wx-0.11.0: dependency base-4.0.0.0 doesn't exist dependency stm-2.1.1.2 doesn't exist There are problems in package wx-0.11.1.2: dependency base-4.0.0.0 doesn't exist dependency stm-2.1.1.2 doesn't exist dependency wxcore-0.11.1.2 doesn't exist There are problems in package bimap-0.2.4: dependency base-3.0.3.0 doesn't exist dependency containers-0.2.0.0 doesn't exist There are problems in package encoding-0.5.1: dependency array-0.2.0.0 doesn't exist dependency base-3.0.3.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency template-haskell-2.3.0.0 doesn't exist There are problems in package fclabels-0.1: dependency base-3.0.3.0 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency template-haskell-2.3.0.0 doesn't exist There are problems in package hscolour-1.11: dependency base-3.0.3.0 doesn't exist There are problems in package parsec-3.0.0: dependency base-3.0.3.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency mtl-1.1.0.2 doesn't exist There are problems in package pureMD5-0.2.4: dependency base-3.0.3.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist There are problems in package salvia-0.1.1: dependency base-3.0.3.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency filepath-1.1.0.1 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-locale-1.0.0.1 doesn't exist dependency random-1.0.0.1 doesn't exist dependency stm-2.1.1.2 doesn't exist There are problems in package salvia-extras-0.1.1: dependency base-3.0.3.0 doesn't exist There are problems in package Diff-0.1.2: dependency array-0.2.0.0 doesn't exist dependency base-3.0.3.0 doesn't exist There are problems in package clevercss-0.1.1: dependency base-3.0.3.0 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency parsec-2.1.0.1 doesn't exist There are problems in package datetime-0.1: dependency QuickCheck-1.2.0.0 doesn't exist dependency base-3.0.3.0 doesn't exist dependency old-locale-1.0.0.1 doesn't exist dependency old-time-1.0.0.1 doesn't exist There are problems in package nano-md5-0.1.2: dependency base-3.0.3.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist There are problems in package network-2.2.0.1: dependency base-4.0.0.0 doesn't exist dependency parsec-2.1.0.1 doesn't exist There are problems in package split-0.1.1: dependency base-3.0.3.0 doesn't exist There are problems in package xml-1.3.4: dependency base-3.0.3.0 doesn't exist There are problems in package filestore-0.2: dependency base-4.0.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency filepath-1.1.0.1 doesn't exist dependency parsec-2.1.0.1 doesn't exist There are problems in package hsemail-1.3: dependency base-3.0.3.0 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency parsec-2.1.0.1 doesn't exist There are problems in package SMTPClient-1.0.1: dependency base-3.0.3.0 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency old-locale-1.0.0.1 doesn't exist dependency old-time-1.0.0.1 doesn't exist There are problems in package HTTP-4000.0.4: dependency array-0.2.0.0 doesn't exist dependency base-3.0.3.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency parsec-2.1.0.1 doesn't exist There are problems in package happstack-util-0.3: dependency HUnit-1.2.0.3 doesn't exist dependency QuickCheck-1.2.0.0 doesn't exist dependency array-0.2.0.0 doesn't exist dependency base-4.0.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-locale-1.0.0.1 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency parsec-2.1.0.1 doesn't exist dependency random-1.0.0.1 doesn't exist dependency template-haskell-2.3.0.0 doesn't exist There are problems in package happstack-data-0.3: dependency HUnit-1.2.0.3 doesn't exist dependency base-4.0.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency pretty-1.0.1.0 doesn't exist dependency syb-0.1.0.0 doesn't exist dependency template-haskell-2.3.0.0 doesn't exist There are problems in package happstack-state-0.3: dependency HUnit-1.2.0.3 doesn't exist dependency base-4.0.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency filepath-1.1.0.1 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency random-1.0.0.1 doesn't exist dependency stm-2.1.1.2 doesn't exist dependency syb-0.1.0.0 doesn't exist dependency template-haskell-2.3.0.0 doesn't exist dependency unix-2.3.1.0 doesn't exist There are problems in package happstack-ixset-0.3: dependency HUnit-1.2.0.3 doesn't exist dependency base-4.0.0.0 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency syb-0.1.0.0 doesn't exist dependency template-haskell-2.3.0.0 doesn't exist There are problems in package happstack-server-0.3: dependency HUnit-1.2.0.3 doesn't exist dependency base-4.0.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency containers-0.2.0.0 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency html-1.0.1.2 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-locale-1.0.0.1 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency parsec-2.1.0.1 doesn't exist dependency syb-0.1.0.0 doesn't exist dependency template-haskell-2.3.0.0 doesn't exist dependency unix-2.3.1.0 doesn't exist dependency xhtml-3000.2.0.1 doesn't exist There are problems in package happstack-contrib-0.3: dependency HUnit-1.2.0.3 doesn't exist dependency base-4.0.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency syb-0.1.0.0 doesn't exist dependency unix-2.3.1.0 doesn't exist There are problems in package FileManip-0.3.2: dependency base-3.0.3.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency filepath-1.1.0.1 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency unix-2.3.1.0 doesn't exist There are problems in package happstack-0.3: dependency HUnit-1.2.0.3 doesn't exist dependency base-4.0.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency directory-1.0.0.2 doesn't exist dependency filepath-1.1.0.1 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency syb-0.1.0.0 doesn't exist There are problems in package HTTP-4000.0.5: dependency array-0.2.0.0 doesn't exist dependency base-3.0.3.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency mtl-1.1.0.2 doesn't exist dependency old-time-1.0.0.1 doesn't exist dependency parsec-2.1.0.1 doesn't exist There are problems in package haddock-2.4.2: dependency Cabal-1.6.0.3 doesn't exist dependency array-0.2.0.0 doesn't exist dependency base-4.1.0.0 doesn't exist dependency containers-0.2.0.1 doesn't exist dependency directory-1.0.0.3 doesn't exist dependency filepath-1.1.0.2 doesn't exist dependency pretty-1.0.1.0 doesn't exist There are problems in package ghc-6.10.2: dependency Cabal-1.6.0.3 doesn't exist dependency array-0.2.0.0 doesn't exist dependency base-4.1.0.0 doesn't exist dependency bytestring-0.9.1.4 doesn't exist dependency containers-0.2.0.1 doesn't exist dependency directory-1.0.0.3 doesn't exist dependency editline-0.2.1.0 doesn't exist dependency filepath-1.1.0.2 doesn't exist dependency hpc-0.5.0.3 doesn't exist dependency old-time-1.0.0.2 doesn't exist dependency template-haskell-2.3.0.1 doesn't exist dependency unix-2.3.2.0 doesn't exist The following packages are broken, either because they have a problem listed above, or because they depend on a broken package. CC-delcont-0.2 terminfo-0.2.2.1 darcs-2.2.0 extensible-exceptions-0.1.1.0 binary-0.4.4 syb-with-class-0.4 hspread-0.3.1 happstack-state-0.1 happstack-ixset-0.1 happstack-server-0.1 happstack-contrib-0.1 X11-1.4.5 xmonad-0.8.1 utf8-string-0.3.4 X11-xft-0.3 ghc-paths-0.1.0.5 haddock-2.4.1 regex-base-0.93.1 regex-posix-0.94.1 regex-compat-0.92 syb-with-class-0.5.1 terminfo-0.3 time-1.1.2.3 xmonad-contrib-0.8.1 wxcore-0.11.0 process-1.0.1.1 darcs-2.2.1 haskell98-1.0.1.0 HaXml-1.13.3 terminfo-0.3.0.1 hslogger-1.0.7 happstack-util-0.1 happstack-data-0.1 happstack-util-0.1.9 happstack-data-0.1.9 happstack-state-0.1.9 happstack-ixset-0.1.9 MaybeT-0.1.2 zlib-0.5.0.0 happstack-server-0.1.9 happstack-contrib-0.1.9 HJavaScript-0.4.4 cpphs-1.6 harp-0.4 haskell-src-exts-0.4.8 hsx-0.4.8 HJScript-0.4.4 hsp-0.4.5 happstack-0.1.9 Xauth-0.1 byteorder-1.0.0 xhb-0.2.2009.2.21 HStringTemplate-0.4.3 happstack-util-0.2.1 happstack-data-0.2.1 happstack-ixset-0.2.1 happstack-server-0.2.1 happstack-state-0.2.1 happstack-0.2.1 uniplate-1.2.0.3 wx-0.11.0 wx-0.11.1.2 bimap-0.2.4 encoding-0.5.1 fclabels-0.1 hscolour-1.11 parsec-3.0.0 pureMD5-0.2.4 salvia-0.1.1 salvia-extras-0.1.1 Diff-0.1.2 clevercss-0.1.1 datetime-0.1 nano-md5-0.1.2 network-2.2.0.1 split-0.1.1 xml-1.3.4 filestore-0.2 hsemail-1.3 SMTPClient-1.0.1 HTTP-4000.0.4 happstack-util-0.3 happstack-data-0.3 happstack-state-0.3 happstack-ixset-0.3 happstack-server-0.3 happstack-contrib-0.3 FileManip-0.3.2 happstack-0.3 HTTP-4000.0.5 haddock-2.4.2 ghc-6.10.2 Did I do something wrong in the installation step? thanks ... -deech -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090428/48e08f64/attachment-0001.htm From allbery at ece.cmu.edu Tue Apr 28 16:02:50 2009 From: allbery at ece.cmu.edu (Brandon S. Allbery KF8NH) Date: Tue Apr 28 15:48:54 2009 Subject: [Haskell-beginners] Working With TVars In-Reply-To: <594f78210904272243q69118d73w1d02b869f3468337@mail.gmail.com> References: <594f78210904272243q69118d73w1d02b869f3468337@mail.gmail.com> Message-ID: <687B50C3-69E9-42F0-B870-5064DDF5E215@ece.cmu.edu> Skipped content of type multipart/alternative-------------- next part -------------- A non-text attachment was scrubbed... Name: PGP.sig Type: application/pgp-signature Size: 195 bytes Desc: This is a digitally signed message part Url : http://www.haskell.org/pipermail/beginners/attachments/20090428/689a08eb/PGP.bin From voigt at tcs.inf.tu-dresden.de Wed Apr 29 15:00:28 2009 From: voigt at tcs.inf.tu-dresden.de (voigt@tcs.inf.tu-dresden.de) Date: Wed Apr 29 14:46:12 2009 Subject: [Haskell-beginners] International Summer School on Advances in Programming Languages Message-ID: <839f2e88adda3a8cd59b480d49900d28.squirrel@mail.tcs.inf.tu-dresden.de> International Summer School on Advances in Programming Languages 25th-28th August, 2009 Heriot-Watt University, Edinburgh, Scotland http://www.macs.hw.ac.uk/~greg/ISS-AiPL Overview This four-day residential International Summer School on Advances in Programming Languages has a major theme of Concurrency, Distribution, and Multicore. Intended primarily for postgraduate research students, the School offers lectures and practical sessions on an engaging blend of cutting edge theoretical and practical techniques from international experts. The Summer School is supported by the Scottish Informatics and Computer Science Alliance (http://www.sicsa.ac.uk/), a Scottish Funding Council Research Pool. Participants from SICSA member institutions may attend at no cost. Confirmed Topics/Speakers - Static and dynamic languages, Prof Phillip Wadler, University of Edinburgh - Compiler technology for data-parallel languages, Dr Sven-Bodo Scholz, University of Hertfordshire - New applications of parametricity, Dr Janis Voigtlaender, Technical University of Dresden - Automatic vectorising compilation, Dr Paul Cockshott, University of Glasgow - Foundational aspects of size analysis, Prof Marko van Eekelen/Dr Olha Shakaravska, Radboud University Nijmegen - Context oriented programming, Dr Pascal Costanza, Vrije Universiteit Brussel - Multi-core programming, Dr Phil Trinder, Heriot-Watt University - Multi-core compilation, Dr Alastair Donaldson, Codeplay Software Ltd - Principles and Applications of Refinement Types, Dr Andrew D. Gordon, Microsoft Research, Cambridge - Resource aware programming in Hume, Prof Greg Michaelson, Heriot-Watt University/ Prof Kevin Hammond, University of St Andrews - Haskell concurrency & parallelism, Dr Satnam Singh, Microsoft Research, Cambridge Location The Summer School is based at Heriot-Watt University's Riccarton campus, set in pleasant parkland to the west of Edinburgh, with easy access to the airport, city and central Scotland: http://www.hw.ac.uk/welcome/directions.htm. The Summer School immediately precedes the 2009 International Conference on Functional Programming (http://www.cs.nott.ac.uk/~gmh/icfp09.html) and takes place during the Edinburgh International Festival (http://www.eif.co.uk/), and the associated Edinburgh Festival Fringe (http://www.edfringe.com/) and Edinburgh International Book Festival (http://www.edbookfest.co.uk/). Steering Committee Prof Greg Michaelson, Heriot-Watt University (Convenor) (mailto:G.Michaelson@hw.ac.uk) Prof Kevin Hammond, University of St Andrews Dr Patricia Johann, University of Strathclyde Prof Phillip Wadler, University of Edinburgh -------------- next part -------------- A non-text attachment was scrubbed... Name: SICSA ISS AiPL.pdf Type: application/download Size: 34222 bytes Desc: not available Url : http://www.haskell.org/pipermail/beginners/attachments/20090429/a6c43702/SICSAISSAiPL-0001.bin -------------- next part -------------- A non-text attachment was scrubbed... Name: SICSA ISS AiPL Programme.pdf Type: application/download Size: 5515 bytes Desc: not available Url : http://www.haskell.org/pipermail/beginners/attachments/20090429/a6c43702/SICSAISSAiPLProgramme-0001.bin From bwsanders at gmail.com Wed Apr 29 15:00:59 2009 From: bwsanders at gmail.com (Ben Sanders) Date: Wed Apr 29 14:46:43 2009 Subject: [Haskell-beginners] Simplifying a 'split' function Message-ID: In looking through a merge sort implementation example, I came across this code: split :: [a] -> [[a]] split [] = [] split (x:xs) = [x] : split xs I would have written the same code as split :: [a] -> [[a]] split = map (: []) Is there any particular difference here (other than explicit recursion)? And is there any other nicer way to write it? Thanks, Ben Sanders From tom.davie at gmail.com Wed Apr 29 15:55:05 2009 From: tom.davie at gmail.com (Thomas Davie) Date: Wed Apr 29 15:40:53 2009 Subject: [Haskell-beginners] Simplifying a 'split' function In-Reply-To: References: Message-ID: <50DB0726-A0D4-4832-96E1-4D7E5DDA2CFE@gmail.com> On 29 Apr 2009, at 21:00, Ben Sanders wrote: > In looking through a merge sort implementation example, I came > across this code: > > split :: [a] -> [[a]] > split [] = [] > split (x:xs) = [x] : split xs > > I would have written the same code as > > split :: [a] -> [[a]] > split = map (: []) > > Is there any particular difference here (other than explicit > recursion)? And is there any other nicer way to write it? How about map pure. I do like the robot monkey though :) Bob From es at ertes.de Wed Apr 29 15:56:05 2009 From: es at ertes.de (Ertugrul Soeylemez) Date: Wed Apr 29 15:41:44 2009 Subject: [Haskell-beginners] Re: Simplifying a 'split' function References: Message-ID: <20090429215605.0c1f28f6@tritium.xx> Ben Sanders wrote: > In looking through a merge sort implementation example, I came across > this code: > > split :: [a] -> [[a]] > split [] = [] > split (x:xs) = [x] : split xs > > I would have written the same code as > > split :: [a] -> [[a]] > split = map (: []) > > Is there any particular difference here (other than explicit > recursion)? No. > And is there any other nicer way to write it? Yes: split = fmap return Greets, Ertugrul. -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://blog.ertes.de/ From bwsanders at gmail.com Wed Apr 29 16:12:07 2009 From: bwsanders at gmail.com (Ben Sanders) Date: Wed Apr 29 16:05:56 2009 Subject: [Haskell-beginners] Simplifying a 'split' function In-Reply-To: <50DB0726-A0D4-4832-96E1-4D7E5DDA2CFE@gmail.com> References: <50DB0726-A0D4-4832-96E1-4D7E5DDA2CFE@gmail.com> Message-ID: > How about map pure. ?I do like the robot monkey though :) > > Bob What is 'map pure'? And it took me a minute to figure out where you were getting 'robot monkey' from :) > split = fmap return >Greets, >Ertugrul. Awesome! Thanks!! From daniel.carrera at theingots.org Wed Apr 29 18:11:26 2009 From: daniel.carrera at theingots.org (Daniel Carrera) Date: Wed Apr 29 17:57:12 2009 Subject: [Haskell-beginners] Selecting a GUI toolkit Message-ID: <49F8D08E.208@theingots.org> Hello, This question is just idle curiosity. I don't actually plan to write a desktop GUI program. With that said, what library would you recommend to someone who wants to write a cross-platform desktop app with Haskell? Consider the following requirements: 1) Cross-platform. Windows, Linux and preferably OS X too. 2) Maintained, stable, mature, documented, etc. 3) Easy to use. Notice that this has much to do with the Haskell bindings. For example, Qt might be a fabulous toolkit, but qtHaskell might be immature (it looks like it started in Dec 2007). wxHaskell looks good. I like the idea behind wxWidgets, but I have never used it (or any GUI toolkit for that matter). Thank you for your input. Cheers, Daniel. From felipe.lessa at gmail.com Wed Apr 29 18:33:25 2009 From: felipe.lessa at gmail.com (Felipe Lessa) Date: Wed Apr 29 18:19:20 2009 Subject: [Haskell-beginners] Selecting a GUI toolkit In-Reply-To: <49F8D08E.208@theingots.org> References: <49F8D08E.208@theingots.org> Message-ID: <20090429223325.GD32272@kira.casa> If I were to write one right now (and I might actually need in a few days), I'd use Gtk2Hs. Cons: - Does not fit Haskell's style. - Very imperative, everything in IO. Pros: - Terrific binding: (almost) complete, working, tested. - Multi-platform (as far as Gtk itself is). - If you need, reading Gtk's C docs is straightforward. - Seamless integration with Cairo (yay!). - ... (probably more) I already used Gtk on other languages before Haskell, though, so I'm somewhat biased. -- Felipe. From daniel.carrera at theingots.org Wed Apr 29 18:40:54 2009 From: daniel.carrera at theingots.org (Daniel Carrera) Date: Wed Apr 29 18:26:38 2009 Subject: [Haskell-beginners] Selecting a GUI toolkit In-Reply-To: <20090429223325.GD32272@kira.casa> References: <49F8D08E.208@theingots.org> <20090429223325.GD32272@kira.casa> Message-ID: <49F8D776.9000004@theingots.org> Hi Felipe, I think I read somewhere that Gtk2Hs is the more active project, so it might be more mature. On the other hand, Gtk kinda sucks on Mac OS X. I hate how Gimp or GnuCash look when I run them on OS X. On Windows Gtk runs fine except that the file browser looks out of place. Daniel. Felipe Lessa wrote: > If I were to write one right now (and I might actually need in a > few days), I'd use Gtk2Hs. > > Cons: > - Does not fit Haskell's style. > - Very imperative, everything in IO. > > Pros: > - Terrific binding: (almost) complete, working, tested. > - Multi-platform (as far as Gtk itself is). > - If you need, reading Gtk's C docs is straightforward. > - Seamless integration with Cairo (yay!). > - ... (probably more) > > I already used Gtk on other languages before Haskell, though, so > I'm somewhat biased. > > -- > Felipe. > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > From lazycat.manatee at gmail.com Wed Apr 29 20:21:08 2009 From: lazycat.manatee at gmail.com (Andy Stewart) Date: Wed Apr 29 20:53:59 2009 Subject: [Haskell-beginners] Re: Selecting a GUI toolkit References: <49F8D08E.208@theingots.org> Message-ID: <871vrbvvnv.fsf@ubuntu.domain> Hi Daniel, Daniel Carrera writes: > Hello, > > This question is just idle curiosity. I don't actually plan to write a desktop GUI program. With > that said, what library would you recommend to someone who wants to write a cross-platform desktop > app with Haskell? > > Consider the following requirements: > > 1) Cross-platform. Windows, Linux and preferably OS X too. > 2) Maintained, stable, mature, documented, etc. > 3) Easy to use. I use gtk2hs, it yes to all your need above. I use gtk2hs-0.10.0 with GHC 6.10 (6.10.1 or 6.10.2) in Ubuntu (or Debian). Below is detail install method: 1) Install GHC 6.10, :) 2) Install depend libraries: sudo aptitude install automake libglade2-dev libgtksourceview-dev libgtksourceview2.0-dev libgconf2-dev librsvg2-dev libgstreamer-plugins-base0.10-dev libgstreamer0.10-dev libgtkglext1-dev libgnomevfs2-dev xulrunner-dev -y 3) Download gtk2hs-0.10.0: http://downloads.sourceforge.net/gtk2hs/gtk2hs-0.10.0.tar.gz 4) Compile gtk2hs-0.10.0: autoconf && ./configure --enable-docs && make && sudo make install And this have tutorial that introduce how to use gtk2hs: http://darcs.haskell.org/gtk2hs/docs/tutorial/Tutorial_Port/ -- Andy > > Notice that this has much to do with the Haskell bindings. For example, Qt might be a fabulous > toolkit, but qtHaskell might be immature (it looks like it started in Dec 2007). > > wxHaskell looks good. I like the idea behind wxWidgets, but I have never used it (or any GUI toolkit > for that matter). > > Thank you for your input. > > Cheers, > Daniel. From felipe.lessa at gmail.com Wed Apr 29 21:15:25 2009 From: felipe.lessa at gmail.com (Felipe Lessa) Date: Wed Apr 29 21:01:17 2009 Subject: [Haskell-beginners] Selecting a GUI toolkit In-Reply-To: <49F8D776.9000004@theingots.org> References: <49F8D08E.208@theingots.org> <20090429223325.GD32272@kira.casa> <49F8D776.9000004@theingots.org> Message-ID: <20090430011525.GA12598@kira.casa> On Thu, Apr 30, 2009 at 12:40:54AM +0200, Daniel Carrera wrote: > I think I read somewhere that Gtk2Hs is the more active project, so it > might be more mature. On the other hand, Gtk kinda sucks on Mac OS X. I > hate how Gimp or GnuCash look when I run them on OS X. On Windows Gtk > runs fine except that the file browser looks out of place. Although I don't have access to a Mac, people usually don't like Gtk there. But there seems to be a native port somewhere that is going to be merged into Gtk+ someday :). Now, good support today for Mac OS X would be my only reason to go through the wxWindows route. I use Gtk+ because back in the days that I tried wxWindows, it had a terrible appearence when using Gtk as a backend, but probably things improved since then. -- Felipe. From nathanmholden at gmail.com Wed Apr 29 22:25:43 2009 From: nathanmholden at gmail.com (Nathan Holden) Date: Wed Apr 29 22:11:25 2009 Subject: [Haskell-beginners] List Function Message-ID: <305228b20904291925t5d1fa624s3f2e41c69cdfae4d@mail.gmail.com> I don't know what you'd call it. Is there a function in any of the basic functions that does this something like this: Sending two lists, [1,2,3] and [2,3,4] it would return [(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)]. I managed to code my way into returning a list of lists, which works. But it seemed like a very basic list/matrix function, so I honestly believe that the Haskell designers probably would've put it in. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090429/16efece4/attachment-0001.htm From ezyang at MIT.EDU Wed Apr 29 22:38:40 2009 From: ezyang at MIT.EDU (Edward Z. Yang) Date: Wed Apr 29 22:24:25 2009 Subject: [Haskell-beginners] List Function In-Reply-To: <305228b20904291925t5d1fa624s3f2e41c69cdfae4d@mail.gmail.com> References: <305228b20904291925t5d1fa624s3f2e41c69cdfae4d@mail.gmail.com> Message-ID: <1241058889-sup-1566@javelin> Excerpts from Nathan Holden's message of Wed Apr 29 22:25:43 -0400 2009: > Sending two lists, [1,2,3] and [2,3,4] it would return > [(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)]. I managed to code > my way into returning a list of lists, which works. But it seemed like a > very basic list/matrix function, so I honestly believe that the Haskell > designers probably would've put it in. Did you mean [1,2,3] and [4,5,6]? Cheers, Edward From jfredett at gmail.com Wed Apr 29 22:39:18 2009 From: jfredett at gmail.com (Joe Fredette) Date: Wed Apr 29 22:25:01 2009 Subject: [Haskell-beginners] List Function In-Reply-To: <305228b20904291925t5d1fa624s3f2e41c69cdfae4d@mail.gmail.com> References: <305228b20904291925t5d1fa624s3f2e41c69cdfae4d@mail.gmail.com> Message-ID: <49F90F56.9030407@gmail.com> So, two ways you could do it. I assume your current function looks like: toPairs :: [a] -> [a] -> [[a]] toPairs [] _ = [] toPairs (x:xs) ls = (zip (\y -> (x,y)) ls) : (toPairs xs ls) This returns something like: toPairs [1,2] [3,4] ===> [[(1,3),(1,4)],[(2,3),(2,4)]] We want a function that takes this list-of-lists to a list. We can certainly see the type as: foo :: [[a]] -> [a] `foo` would have to take all the elements of each list, and put it in a new one. We know of a function which combines the elements of two lists, (++) so really, our foo function would do: foo [] = [] foo (x:xs) = x ++ foo xs concatenating all of the lists together in order. But this is just a fold, we can call foo: foo = foldr (++) -- or foldl would work too. foldr is just the pattern above, abstracted away to a convenient function. Of course, this function comes up all the time, so we have one in the prelude, it's called. `concat`. and if you look up the source on hoogle, I believe you'll find the above. Nathan Holden wrote: > I don't know what you'd call it. Is there a function in any of the > basic functions that does this something like this: > > Sending two lists, [1,2,3] and [2,3,4] it would return > [(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)]. I managed to > code my way into returning a list of lists, which works. But it seemed > like a very basic list/matrix function, so I honestly believe that the > Haskell designers probably would've put it in. > ------------------------------------------------------------------------ > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -------------- next part -------------- A non-text attachment was scrubbed... Name: jfredett.vcf Type: text/x-vcard Size: 296 bytes Desc: not available Url : http://www.haskell.org/pipermail/beginners/attachments/20090429/e6863019/jfredett.vcf From ezyang at MIT.EDU Wed Apr 29 22:41:15 2009 From: ezyang at MIT.EDU (Edward Z. Yang) Date: Wed Apr 29 22:26:58 2009 Subject: [Haskell-beginners] List Function In-Reply-To: <1241058889-sup-1566@javelin> References: <305228b20904291925t5d1fa624s3f2e41c69cdfae4d@mail.gmail.com> <1241058889-sup-1566@javelin> Message-ID: <1241059179-sup-7293@javelin> Excerpts from Edward Z. Yang's message of Wed Apr 29 22:38:40 -0400 2009: > Excerpts from Nathan Holden's message of Wed Apr 29 22:25:43 -0400 2009: > > Sending two lists, [1,2,3] and [2,3,4] it would return > > [(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)]. I managed to code > > my way into returning a list of lists, which works. But it seemed like a > > very basic list/matrix function, so I honestly believe that the Haskell > > designers probably would've put it in. > > Did you mean [1,2,3] and [4,5,6]? To elaborate, a list comprehension is what you want, if you want this function to do what I think you want it to do. Prelude> let f as bs = [(a,b) | a <- as, b <- bs] Prelude> f [1,2,3] [4,5,6] [(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)] Cheers, Edward From jfredett at gmail.com Wed Apr 29 22:48:42 2009 From: jfredett at gmail.com (Joe Fredette) Date: Wed Apr 29 22:34:26 2009 Subject: [Haskell-beginners] List Function In-Reply-To: <49F90F56.9030407@gmail.com> References: <305228b20904291925t5d1fa624s3f2e41c69cdfae4d@mail.gmail.com> <49F90F56.9030407@gmail.com> Message-ID: <49F9118A.1080504@gmail.com> Occurs to me I said two ways, and only gave one, the one I gave was the tougher way. The easiest way is to use a list comprehension, viz: toPairs xs ys = [(x,y) | x <- xs, y <- ys] This is nice and succint, you can think of it (assuming you're familiar with it) as set-builder notation. The '[' and ']' brackets are the set brackets '{' and '}'. '<-' is roughly like the element symbol. You can even add constraints (called guards), like so: foo xs ys = [x / y | x <- xs, y <- ys, y /= 0] Joe Fredette wrote: > So, two ways you could do it. > > I assume your current function looks like: > > toPairs :: [a] -> [a] -> [[a]] > toPairs [] _ = [] > toPairs (x:xs) ls = (zip (\y -> (x,y)) ls) : (toPairs xs ls) > > This returns something like: > > toPairs [1,2] [3,4] ===> [[(1,3),(1,4)],[(2,3),(2,4)]] > > We want a function that takes this list-of-lists to a list. We can > certainly see the type as: > > foo :: [[a]] -> [a] > > `foo` would have to take all the elements of each list, and put it in > a new one. We know of a function which combines the elements of two > lists, (++) > so really, our foo function would do: > > foo [] = [] > foo (x:xs) = x ++ foo xs > > concatenating all of the lists together in order. But this is just a > fold, we can call foo: > > foo = foldr (++) -- or foldl would work too. > > foldr is just the pattern above, abstracted away to a convenient > function. > > Of course, this function comes up all the time, so we have one in the > prelude, it's called. `concat`. and if you look up the source on > hoogle, I believe you'll find the above. > > Nathan Holden wrote: >> I don't know what you'd call it. Is there a function in any of the >> basic functions that does this something like this: >> >> Sending two lists, [1,2,3] and [2,3,4] it would return >> [(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)]. I managed to >> code my way into returning a list of lists, which works. But it >> seemed like a very basic list/matrix function, so I honestly believe >> that the Haskell designers probably would've put it in. >> ------------------------------------------------------------------------ >> >> _______________________________________________ >> Beginners mailing list >> Beginners@haskell.org >> http://www.haskell.org/mailman/listinfo/beginners >> -------------- next part -------------- A non-text attachment was scrubbed... Name: jfredett.vcf Type: text/x-vcard Size: 296 bytes Desc: not available Url : http://www.haskell.org/pipermail/beginners/attachments/20090429/6e12a534/jfredett.vcf From mpm at alumni.caltech.edu Wed Apr 29 23:18:27 2009 From: mpm at alumni.caltech.edu (Michael P Mossey) Date: Wed Apr 29 23:04:24 2009 Subject: [Haskell-beginners] putting in a good word for "Haskell: The Craft of Functional Programming" Message-ID: <49F91883.30608@alumni.caltech.edu> I'm working through "Haskell: the Craft of Functional Programming" (by Simon Thompson) in depth, and I want to put in a good word for it. His exercises are numerous and they seem to lead me from simpler ideas to more complex ideas in a natural way. As part of learning Haskell, I actually started with other books and tutorials and skipped around in them, reading some of the later chapters before the earlier ones. I like that sometimes. But I'm finding that Thompson's book is helpful for getting an intuition for the language, as opposed to just reading about its features, so I'm working it in order. My other books include "Real World Haskell" and "School of Expression." The wonderful thing about RWH is that it's available online (I do own a hardcopy) where people comment on the text and exercises. -Mike From mpm at alumni.caltech.edu Wed Apr 29 23:20:23 2009 From: mpm at alumni.caltech.edu (Michael P Mossey) Date: Wed Apr 29 23:06:10 2009 Subject: [Haskell-beginners] P.S. "Haskell: Craft of Functional Programming" Message-ID: <49F918F7.5020907@alumni.caltech.edu> Oh, and I got HCFP at the local Border's. Apparently it's selling well enough to include it in a general bookstore. Look out Stephen King---Simon Thompson is coming! From byorgey at seas.upenn.edu Wed Apr 29 23:41:03 2009 From: byorgey at seas.upenn.edu (Brent Yorgey) Date: Wed Apr 29 23:26:45 2009 Subject: [Haskell-beginners] List Function In-Reply-To: <305228b20904291925t5d1fa624s3f2e41c69cdfae4d@mail.gmail.com> References: <305228b20904291925t5d1fa624s3f2e41c69cdfae4d@mail.gmail.com> Message-ID: <20090430034103.GA17882@seas.upenn.edu> On Wed, Apr 29, 2009 at 10:25:43PM -0400, Nathan Holden wrote: > I don't know what you'd call it. Is there a function in any of the basic > functions that does this something like this: > > Sending two lists, [1,2,3] and [2,3,4] it would return > [(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)]. I managed to code > my way into returning a list of lists, which works. But it seemed like a > very basic list/matrix function, so I honestly believe that the Haskell > designers probably would've put it in. Others' answers are probably more helpful for learning, but I also wanted to point out that there is a Prelude function that does something close to this (assuming you meant [4,5,6]), namely, 'sequence'. Prelude> sequence [ [1,2,3], [4,5,6] ] [[1,4],[1,5],[1,6],[2,4],[2,5],[2,6],[3,4],[3,5],[3,6]] Prelude> sequence [ [1,2], [3,4,5], [6,7] ] [[1,3,6],[1,3,7],[1,4,6],[1,4,7],[1,5,6],[1,5,7],[2,3,6],[2,3,7],[2,4,6],[2,4,7],[2,5,6],[2,5,7]] However, explaining how/why sequence does this requires understanding the list monad, which you may or may not want to tackle at this point. If you import 'Control.Applicative' you can even do exactly what you wanted, with pairs and all: Prelude Control.Applicative> liftA2 (,) [1,2,3] [4,5,6] [(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)] Here, liftA2 is applying the function (,) to every possible pair of values from the two lists. -Brent From ezyang at MIT.EDU Wed Apr 29 23:57:08 2009 From: ezyang at MIT.EDU (Edward Z. Yang) Date: Wed Apr 29 23:42:51 2009 Subject: [Haskell-beginners] List Function In-Reply-To: <20090430034103.GA17882@seas.upenn.edu> References: <305228b20904291925t5d1fa624s3f2e41c69cdfae4d@mail.gmail.com> <20090430034103.GA17882@seas.upenn.edu> Message-ID: <1241063266-sup-1450@javelin> Excerpts from Brent Yorgey's message of Wed Apr 29 23:41:03 -0400 2009: > Others' answers are probably more helpful for learning, but I also > wanted to point out that there is a Prelude function that does > something close to this (assuming you meant [4,5,6]), namely, > 'sequence'. > > Prelude> sequence [ [1,2,3], [4,5,6] ] > [[1,4],[1,5],[1,6],[2,4],[2,5],[2,6],[3,4],[3,5],[3,6]] > Prelude> sequence [ [1,2], [3,4,5], [6,7] ] > > [[1,3,6],[1,3,7],[1,4,6],[1,4,7],[1,5,6],[1,5,7],[2,3,6],[2,3,7],[2,4,6],[2,4,7] > ,[2,5,6],[2,5,7]] > > However, explaining how/why sequence does this requires understanding > the list monad, which you may or may not want to tackle at this point. Interesting! According to Hoogle, the sequence function evaluates each monad and then collects the results. I know evaluating a list monad returns a list, but what do they mean by "collect"? > If you import 'Control.Applicative' you can even do exactly what you > wanted, with pairs and all: > > Prelude Control.Applicative> liftA2 (,) [1,2,3] [4,5,6] > [(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)] > > Here, liftA2 is applying the function (,) to every possible pair of > values from the two lists. I'm not even going to try to understand that now. Cheers, Edward From kaushalkp at gmail.com Wed Apr 29 09:05:24 2009 From: kaushalkp at gmail.com (kaushal Pathak) Date: Thu Apr 30 01:29:56 2009 Subject: [Haskell-beginners] Need Help In-Reply-To: References: <6d9efa350904110516u6d6447cckdfa20c8edf1f85a5@mail.gmail.com> Message-ID: <6d9efa350904290605r4361a47do3caba24eee9681f@mail.gmail.com> Here is another one liner I am stuck at(Find permuation of string), here is my one line code : permute myStr = foldr(\x acc -> (zipWith (\x1 y1 -> x1 ++ [x] ++ y1) (inits acc) (tails acc))) [] myStr and here is 5 line error ;-( Occurs check: cannot construct the infinite type: a = [a] Expected type: [a] Inferred type: [[a]] In the expression: (zipWith (\ x1 y1 -> x1 ++ x ++ y1) (inits acc) (tails acc)) In the first argument of `foldr', namely `(\ x acc -> (zipWith (\ x1 y1 -> x1 ++ x ++ y1) (inits acc) (tails acc)))' Will really appreciate your help in moving ahead Regards Kaushal -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090429/39380333/attachment-0001.htm From kaushalkp at gmail.com Wed Apr 29 09:44:21 2009 From: kaushalkp at gmail.com (kaushal Pathak) Date: Thu Apr 30 01:30:20 2009 Subject: [Haskell-beginners] Need Help In-Reply-To: <6d9efa350904290605r4361a47do3caba24eee9681f@mail.gmail.com> References: <6d9efa350904110516u6d6447cckdfa20c8edf1f85a5@mail.gmail.com> <6d9efa350904290605r4361a47do3caba24eee9681f@mail.gmail.com> Message-ID: <6d9efa350904290644j22f828bfu9b19f97b7771adce@mail.gmail.com> Whats the issue with following pgm to find permutation of a string permute myStr = foldl(\acc x1 -> (foldr(\x2 acc1 -> (zipWith (\x3 y3 -> x3 ++ [x1] ++ y3) (inits acc1) (tails acc1))) [] acc)) [] myStr On Wed, Apr 29, 2009 at 6:35 PM, kaushal Pathak wrote: > Here is another one liner I am stuck at(Find permuation of string), here is > my one line code : > > permute myStr = foldr(\x acc -> (zipWith (\x1 y1 -> x1 ++ [x] ++ y1) (inits > acc) (tails acc))) [] myStr > > and here is 5 line error ;-( > > Occurs check: cannot construct the infinite type: a = [a] > Expected type: [a] > Inferred type: [[a]] > In the expression: > (zipWith (\ x1 y1 -> x1 ++ x ++ y1) (inits acc) (tails acc)) > In the first argument of `foldr', namely > `(\ x acc > -> (zipWith (\ x1 y1 -> x1 ++ x ++ y1) (inits acc) (tails > acc)))' > > > Will really appreciate your help in moving ahead > > Regards > Kaushal > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090429/2442e1d8/attachment.htm From gale at sefer.org Thu Apr 30 03:22:30 2009 From: gale at sefer.org (Yitzchak Gale) Date: Thu Apr 30 03:08:32 2009 Subject: [Haskell-beginners] List Function In-Reply-To: <1241063266-sup-1450@javelin> References: <305228b20904291925t5d1fa624s3f2e41c69cdfae4d@mail.gmail.com> <20090430034103.GA17882@seas.upenn.edu> <1241063266-sup-1450@javelin> Message-ID: <2608b8a80904300022v6524122fm231db767c6e2b974@mail.gmail.com> Brent Yorgey wrote: >> ? Prelude Control.Applicative> liftA2 (,) [1,2,3] [4,5,6] >> ? [(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)] Edward Z. Yang wrote: > I'm not even going to try to understand that now. Brent used that because Applicative is even simpler than Monad - at least theoretically. But it's less well known at the moment. If you want to stick to Monad, Brent's method works there too: Prelude Control.Monad> liftM2 (,) [1,2,3] [4,5,6] [(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)] -Yitz From apfelmus at quantentunnel.de Thu Apr 30 03:57:25 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Thu Apr 30 03:43:19 2009 Subject: [Haskell-beginners] Re: List Function In-Reply-To: <1241063266-sup-1450@javelin> References: <305228b20904291925t5d1fa624s3f2e41c69cdfae4d@mail.gmail.com> <20090430034103.GA17882@seas.upenn.edu> <1241063266-sup-1450@javelin> Message-ID: Edward Z. Yang wrote: >> However, explaining how/why sequence does this requires understanding >> the list monad, which you may or may not want to tackle at this point. > > Interesting! According to Hoogle, the sequence function evaluates each > monad and then collects the results. I know evaluating a list monad returns > a list, but what do they mean by "collect"? There is also sequence_ which does not collect the results, but throws them away. Prelude> sequence_ [ [1,2,3], [4,5,6] ] [(),(),(),(),(),(),(),(),()] (Also, concerning terminology, sequence evaluates each monadic action. You can't evaluate a monad, it's a type constructor, not a function or value.) >> If you import 'Control.Applicative' you can even do exactly what you >> wanted, with pairs and all: >> >> Prelude Control.Applicative> liftA2 (,) [1,2,3] [4,5,6] >> [(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)] >> >> Here, liftA2 is applying the function (,) to every possible pair of >> values from the two lists. > > I'm not even going to try to understand that now. Also known as liftM2 (,) [1,2,3] [4,5,6] Which is the same as do x <- [1,2,3] y <- [4,5,6] return (x,y) Regards, apfelmus -- http://apfelmus.nfshost.com From apfelmus at quantentunnel.de Thu Apr 30 04:00:08 2009 From: apfelmus at quantentunnel.de (Heinrich Apfelmus) Date: Thu Apr 30 03:50:49 2009 Subject: [Haskell-beginners] Re: Selecting a GUI toolkit In-Reply-To: <20090430011525.GA12598@kira.casa> References: <49F8D08E.208@theingots.org> <20090429223325.GD32272@kira.casa> <49F8D776.9000004@theingots.org> <20090430011525.GA12598@kira.casa> Message-ID: Felipe Lessa wrote: > Daniel Carrera wrote: >> I think I read somewhere that Gtk2Hs is the more active project, so it >> might be more mature. On the other hand, Gtk kinda sucks on Mac OS X. I >> hate how Gimp or GnuCash look when I run them on OS X. On Windows Gtk >> runs fine except that the file browser looks out of place. > > Although I don't have access to a Mac, people usually don't like > Gtk there. But there seems to be a native port somewhere that is > going to be merged into Gtk+ someday :). I think the "native" refers not to the GUI appearance but to the feature that you don't need an X server to run a Gtk application anymore. > Now, good support today for Mac OS X would be my only reason to > go through the wxWindows route. I use Gtk+ because back in the > days that I tried wxWindows, it had a terrible appearence when > using Gtk as a backend, but probably things improved since then. WxWindows on Mac OS X doesn't really look great either, I'm afraid. Regards, apfelmus -- http://apfelmus.nfshost.com From daniel.carrera at theingots.org Thu Apr 30 04:41:19 2009 From: daniel.carrera at theingots.org (Daniel Carrera) Date: Thu Apr 30 04:27:03 2009 Subject: [Haskell-beginners] Selecting a GUI toolkit In-Reply-To: <20090430011525.GA12598@kira.casa> References: <49F8D08E.208@theingots.org> <20090429223325.GD32272@kira.casa> <49F8D776.9000004@theingots.org> <20090430011525.GA12598@kira.casa> Message-ID: <49F9642F.8010809@theingots.org> Felipe Lessa wrote: > Although I don't have access to a Mac, people usually don't like > Gtk there. But there seems to be a native port somewhere that is > going to be merged into Gtk+ someday :). > > Now, good support today for Mac OS X would be my only reason to > go through the wxWindows route. I use Gtk+ because back in the > days that I tried wxWindows, it had a terrible appearence when > using Gtk as a backend, but probably things improved since then. Thanks. I guess one would have to try making a simple program with each and see. After all, one of the selling points of WX is that it's supposed to look right in all platforms. I have been sort of assuming that between WX and Gtk you might as well pick WX because WX uses Gtk in the platforms where Gtk looks right. The choice would be simpler if Gtk ran natively on Mac. Right now it looks horrible and it is hard to setup if you are not a technical person or don't have the latest OS X. At a *minimum* you'll need to install fink or mac ports and run the program from the terminal. Btw, I have read the first few chapters of the Gtk2Hs tutorial. The code looks extremely imperative. Even more than wxHaskell. I mean... initGUI, "widgetShowAll window", "mainGUI"... In principle I would be happy with any WX, Gtk and Qt. I think well of all of them. It's just that they all seem to have a lot of limitations. Cheers, Daniel. From daniel.carrera at theingots.org Thu Apr 30 04:44:28 2009 From: daniel.carrera at theingots.org (Daniel Carrera) Date: Thu Apr 30 04:30:10 2009 Subject: [Haskell-beginners] Re: Selecting a GUI toolkit In-Reply-To: References: <49F8D08E.208@theingots.org> <20090429223325.GD32272@kira.casa> <49F8D776.9000004@theingots.org> <20090430011525.GA12598@kira.casa> Message-ID: <49F964EC.4060308@theingots.org> Heinrich Apfelmus wrote: > WxWindows on Mac OS X doesn't really look great either, I'm afraid. Really? The screen shots look good to me. See: http://wxhaskell.sourceforge.net/images/controls-macosx.png Daniel. From tom.davie at gmail.com Thu Apr 30 04:54:26 2009 From: tom.davie at gmail.com (Thomas Davie) Date: Thu Apr 30 04:40:25 2009 Subject: [Haskell-beginners] Re: Selecting a GUI toolkit In-Reply-To: <49F964EC.4060308@theingots.org> References: <49F8D08E.208@theingots.org> <20090429223325.GD32272@kira.casa> <49F8D776.9000004@theingots.org> <20090430011525.GA12598@kira.casa> <49F964EC.4060308@theingots.org> Message-ID: On 30 Apr 2009, at 10:44, Daniel Carrera wrote: > Heinrich Apfelmus wrote: >> WxWindows on Mac OS X doesn't really look great either, I'm afraid. > > Really? The screen shots look good to me. See: > > http://wxhaskell.sourceforge.net/images/controls-macosx.png Really, here's what that *should* look like: http://www.cs.kent.ac.uk/people/rpg/tatd2/controls-macosx.png Of note though, the main problem with WX is not that the controls look different, it's that they behave differently. UI is not just about looks ;). Bob From daniel.carrera at theingots.org Thu Apr 30 05:12:40 2009 From: daniel.carrera at theingots.org (Daniel Carrera) Date: Thu Apr 30 04:58:27 2009 Subject: [Haskell-beginners] Re: Selecting a GUI toolkit In-Reply-To: References: <49F8D08E.208@theingots.org> <20090429223325.GD32272@kira.casa> <49F8D776.9000004@theingots.org> <20090430011525.GA12598@kira.casa> <49F964EC.4060308@theingots.org> Message-ID: <49F96B88.6060709@theingots.org> Thomas Davie wrote: > Really, here's what that *should* look like: > > http://www.cs.kent.ac.uk/people/rpg/tatd2/controls-macosx.png Your link is for Panther, my link was for Jaguar. The wxHaskell also has a screenshot on Panther: http://wxhaskell.sourceforge.net/images/controls-macosx2.png > Of note though, the main problem with WX is not that the controls look > different, it's that they behave differently. UI is not just about > looks ;). Ok.. how do they behave? I bet you that they behave better than the Gtk controls on OS X... ugh. You are right that UI is not just looks. That's another of the issues with X11 on OS X, it behaves wrong. The command key doesn't do anything, so for example, it's a major pain to use Gimp on OS X without a two button mouse. How about Qt? Do you know if Qt behaves well on OS X? I thought that Qt didn't look native on OS X (I'm on Ubuntu right now, so I can't check). Daniel. From tom.davie at gmail.com Thu Apr 30 06:07:13 2009 From: tom.davie at gmail.com (Thomas Davie) Date: Thu Apr 30 05:52:57 2009 Subject: [Haskell-beginners] Re: Selecting a GUI toolkit In-Reply-To: <49F96B88.6060709@theingots.org> References: <49F8D08E.208@theingots.org> <20090429223325.GD32272@kira.casa> <49F8D776.9000004@theingots.org> <20090430011525.GA12598@kira.casa> <49F964EC.4060308@theingots.org> <49F96B88.6060709@theingots.org> Message-ID: On 30 Apr 2009, at 11:12, Daniel Carrera wrote: > Thomas Davie wrote: >> Really, here's what that *should* look like: >> http://www.cs.kent.ac.uk/people/rpg/tatd2/controls-macosx.png > > Your link is for Panther, my link was for Jaguar. The wxHaskell also > has a screenshot on Panther: > > http://wxhaskell.sourceforge.net/images/controls-macosx2.png My link was on leopard actually, but that still looks significantly different to the natively designed UI. > >> Of note though, the main problem with WX is not that the controls >> look different, it's that they behave differently. UI is not just >> about looks ;). > > Ok.. how do they behave? I bet you that they behave better than the > Gtk controls on OS X... ugh. I very much doubt that actually ? mac users in my experience notice when things are annoyingly slightly different from the norm ? a kind of uncanny valley effect, it's almost what you expect, but not quite. In the mean time, gtk being entirely non-OS X like running in X11 says "hey, I'm different, deal with it", and people do. > You are right that UI is not just looks. That's another of the > issues with X11 on OS X, it behaves wrong. The command key doesn't > do anything, so for example, it's a major pain to use Gimp on OS X > without a two button mouse. Well yes, but then all macs come with 2 button mice, so *shrug*. But yes, X11 apps in general behave wrong, and mac users don't like them much, but they like them better than apps that pretend to be OS X like, but don't get it right. > How about Qt? Do you know if Qt behaves well on OS X? I thought that > Qt didn't look native on OS X (I'm on Ubuntu right now, so I can't > check). Qt get closer into uncanny valley than gtk does, because it runs natively. This really though comes down to the fact that it's totally impossible to design cross platform UIs for applications. Different platforms UIs behave differently, so deal with it, and write different UIs for the different platforms. Don't expect everyone to fit into your one- size-fits-all straight jacket. This is extra work, but 1) it enforces a good abstraction layer between your UI and your actual application, and 2) it gives major benefits in terms of happy customers. Bob -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090430/3468665d/attachment-0001.htm From daniel.carrera at theingots.org Thu Apr 30 06:32:31 2009 From: daniel.carrera at theingots.org (Daniel Carrera) Date: Thu Apr 30 06:18:16 2009 Subject: [Haskell-beginners] Re: Selecting a GUI toolkit In-Reply-To: References: <49F8D08E.208@theingots.org> <20090429223325.GD32272@kira.casa> <49F8D776.9000004@theingots.org> <20090430011525.GA12598@kira.casa> <49F964EC.4060308@theingots.org> <49F96B88.6060709@theingots.org> Message-ID: <49F97E3F.5050400@theingots.org> Thomas Davie wrote: >> http://wxhaskell.sourceforge.net/images/controls-macosx2.png > > My link was on leopard actually, but that still looks significantly > different to the natively designed UI. Significantly different? They are practically identical. >> Ok.. how do they behave? I bet you that they behave better than the >> Gtk controls on OS X... ugh. > > I very much doubt that actually ? mac users in my experience notice when > things are annoyingly slightly different from the norm ? a kind of > uncanny valley effect, it's almost what you expect, but not quite. In > the mean time, gtk being entirely non-OS X like running in X11 says > "hey, I'm different, deal with it", and people do. I am a Mac user and I disagree. I know several mac users who also disagree. I remember that NeoOffice used to be much more popular than OpenOffice.org on Mac because OOo used X11 and NeoOffice didn't, even though it was clear that NeoOffice was not quite native. You are the first mac user I meet that feels the way you feel. I have met quite a few mac users who don't share your views. X11 apps look like crap. And I disagree with the "uncanny valley" thing because *native* OS X apps can look quite different. There isn't a single uniform look for native OS X apps but at least two. Looking at the screen shots on the wxHaskell website, if I saw that on my Mac, it wouldn't cross my mind that it isn't native. > Well yes, but then all macs come with 2 button mice, so *shrug*. Mine doesn't and every mac I've seen doesn't, so don't dismiss me like that, it's very rude. Also, in macs the command key is used a lot, you can't just throw it away and "shrug" like you just did. Daniel. From lazycat.manatee at gmail.com Thu Apr 30 05:18:42 2009 From: lazycat.manatee at gmail.com (Andy Stewart) Date: Thu Apr 30 06:54:01 2009 Subject: [Haskell-beginners] Re: Selecting a GUI toolkit References: <49F8D08E.208@theingots.org> <20090429223325.GD32272@kira.casa> <49F8D776.9000004@theingots.org> <20090430011525.GA12598@kira.casa> <49F9642F.8010809@theingots.org> Message-ID: <87tz46lcst.fsf@ubuntu.domain> Daniel Carrera writes: > Felipe Lessa wrote: >> Although I don't have access to a Mac, people usually don't like >> Gtk there. But there seems to be a native port somewhere that is >> going to be merged into Gtk+ someday :). >> >> Now, good support today for Mac OS X would be my only reason to >> go through the wxWindows route. I use Gtk+ because back in the >> days that I tried wxWindows, it had a terrible appearence when >> using Gtk as a backend, but probably things improved since then. > > > Thanks. I guess one would have to try making a simple program with each and see. After all, one of > the selling points of WX is that it's supposed to look right in all platforms. I have been sort of > assuming that between WX and Gtk you might as well pick WX because WX uses Gtk in the platforms > where Gtk looks right. > > The choice would be simpler if Gtk ran natively on Mac. Right now it looks horrible and it is hard > to setup if you are not a technical person or don't have the latest OS X. At a *minimum* you'll need > to install fink or mac ports and run the program from the terminal. > > Btw, I have read the first few chapters of the Gtk2Hs tutorial. The code looks extremely > imperative. Even more than wxHaskell. I mean... initGUI, > "widgetShowAll window", "mainGUI"... Yep, very imperative, but it works. At least gtk2hs is easiest way to build Haskell GUI program. -- Andy From daniel.carrera at theingots.org Thu Apr 30 07:16:18 2009 From: daniel.carrera at theingots.org (Daniel Carrera) Date: Thu Apr 30 07:02:00 2009 Subject: [Haskell-beginners] Re: Selecting a GUI toolkit In-Reply-To: <87tz46lcst.fsf@ubuntu.domain> References: <49F8D08E.208@theingots.org> <20090429223325.GD32272@kira.casa> <49F8D776.9000004@theingots.org> <20090430011525.GA12598@kira.casa> <49F9642F.8010809@theingots.org> <87tz46lcst.fsf@ubuntu.domain> Message-ID: <49F98882.6080606@theingots.org> Andy Stewart wrote: >> Btw, I have read the first few chapters of the Gtk2Hs tutorial. The code looks extremely >> imperative. Even more than wxHaskell. I mean... initGUI, >> "widgetShowAll window", "mainGUI"... > Yep, very imperative, but it works. > At least gtk2hs is easiest way to build Haskell GUI program. Thanks. It's hard to argue with "it works". I'd rather have something that works on two platforms than something that fails on three platforms :-) Have you any experience with wxHaskell? Do you find it harder to use? Or is it more buggy? Daniel. From allbery at ece.cmu.edu Thu Apr 30 08:12:23 2009 From: allbery at ece.cmu.edu (Brandon S. Allbery KF8NH) Date: Thu Apr 30 07:58:16 2009 Subject: [Haskell-beginners] Simplifying a 'split' function In-Reply-To: References: <50DB0726-A0D4-4832-96E1-4D7E5DDA2CFE@gmail.com> Message-ID: <71F1B74B-7820-4029-894C-104024BA07E0@ece.cmu.edu> On Apr 29, 2009, at 16:12 , Ben Sanders wrote: >> How about map pure. I do like the robot monkey though :) > > What is 'map pure'? It uses the applicative functor (Control.Applicative) instance for lists, just as "fmap return" uses the monad instance. Both work out to the same thing. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH -------------- next part -------------- A non-text attachment was scrubbed... Name: PGP.sig Type: application/pgp-signature Size: 195 bytes Desc: This is a digitally signed message part Url : http://www.haskell.org/pipermail/beginners/attachments/20090430/c863206e/PGP.bin From allbery at ece.cmu.edu Thu Apr 30 08:29:25 2009 From: allbery at ece.cmu.edu (Brandon S. Allbery KF8NH) Date: Thu Apr 30 08:15:18 2009 Subject: [Haskell-beginners] List Function In-Reply-To: <1241063266-sup-1450@javelin> References: <305228b20904291925t5d1fa624s3f2e41c69cdfae4d@mail.gmail.com> <20090430034103.GA17882@seas.upenn.edu> <1241063266-sup-1450@javelin> Message-ID: <0C2B938B-B98A-4510-A939-5D15A4E0829C@ece.cmu.edu> On Apr 29, 2009, at 23:57 , Edward Z. Yang wrote: > Excerpts from Brent Yorgey's message of Wed Apr 29 23:41:03 -0400 > 2009: >> Prelude> sequence [ [1,2,3], [4,5,6] ] >> [[1,4],[1,5],[1,6],[2,4],[2,5],[2,6],[3,4],[3,5],[3,6]] >> Prelude> sequence [ [1,2], [3,4,5], [6,7] ] >> >> [[1,3,6],[1,3,7],[1,4,6],[1,4,7],[1,5,6],[1,5,7],[2,3,6],[2,3,7], >> [2,4,6],[2,4,7] >> ,[2,5,6],[2,5,7]] > > Interesting! According to Hoogle, the sequence function evaluates each > monad and then collects the results. I know evaluating a list monad > returns > a list, but what do they mean by "collect"? In the list monad, "collect" means "concatenate". -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH -------------- next part -------------- A non-text attachment was scrubbed... Name: PGP.sig Type: application/pgp-signature Size: 195 bytes Desc: This is a digitally signed message part Url : http://www.haskell.org/pipermail/beginners/attachments/20090430/4c69132c/PGP.bin From patrick.leboutillier at gmail.com Thu Apr 30 13:12:31 2009 From: patrick.leboutillier at gmail.com (Patrick LeBoutillier) Date: Thu Apr 30 12:58:12 2009 Subject: [Haskell-beginners] Parsec tutorial Message-ID: Hi all, I'm looking for a Parsec tutorial that can get me started in writing a simple SQL parser. I can't seem to find a lot using Google. Does anyone have some resources that could be helpful? Thanks a lot, Patrick -- ===================== Patrick LeBoutillier Rosem?re, Qu?bec, Canada From rick.richardson at gmail.com Thu Apr 30 13:22:15 2009 From: rick.richardson at gmail.com (Rick R) Date: Thu Apr 30 13:07:55 2009 Subject: [Haskell-beginners] Parsec tutorial In-Reply-To: References: Message-ID: <9810b81b0904301022s347cfbc2i36e4329b1e18d6c0@mail.gmail.com> http://en.wikibooks.org/wiki/Write_Yourself_a_Scheme_in_48_Hours On Thu, Apr 30, 2009 at 1:12 PM, Patrick LeBoutillier < patrick.leboutillier@gmail.com> wrote: > Hi all, > > I'm looking for a Parsec tutorial that can get me started in writing a > simple SQL parser. > I can't seem to find a lot using Google. Does anyone have some > resources that could be helpful? > > > Thanks a lot, > > Patrick > -- > ===================== > Patrick LeBoutillier > Rosem?re, Qu?bec, Canada > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -- We can't solve problems by using the same kind of thinking we used when we created them. - A. Einstein -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090430/2b845d6b/attachment.htm From aditya.siram at gmail.com Thu Apr 30 13:44:45 2009 From: aditya.siram at gmail.com (aditya siram) Date: Thu Apr 30 13:30:52 2009 Subject: [Haskell-beginners] Parsec tutorial In-Reply-To: <9810b81b0904301022s347cfbc2i36e4329b1e18d6c0@mail.gmail.com> References: <9810b81b0904301022s347cfbc2i36e4329b1e18d6c0@mail.gmail.com> Message-ID: <594f78210904301044j4b8cca5cp6f83db2f107fe866@mail.gmail.com> I learnt to use Parsec from Real World Haskell [1]. hth, deech [1] http://book.realworldhaskell.org/read/using-parsec.html On Thu, Apr 30, 2009 at 12:22 PM, Rick R wrote: > http://en.wikibooks.org/wiki/Write_Yourself_a_Scheme_in_48_Hours > > > On Thu, Apr 30, 2009 at 1:12 PM, Patrick LeBoutillier < > patrick.leboutillier@gmail.com> wrote: > >> Hi all, >> >> I'm looking for a Parsec tutorial that can get me started in writing a >> simple SQL parser. >> I can't seem to find a lot using Google. Does anyone have some >> resources that could be helpful? >> >> >> Thanks a lot, >> >> Patrick >> -- >> ===================== >> Patrick LeBoutillier >> Rosem?re, Qu?bec, Canada >> _______________________________________________ >> Beginners mailing list >> Beginners@haskell.org >> http://www.haskell.org/mailman/listinfo/beginners >> > > > > -- > We can't solve problems by using the same kind of thinking we used when we > created them. > - A. Einstein > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090430/e4b94252/attachment-0001.htm From hydo at mac.com Thu Apr 30 13:55:40 2009 From: hydo at mac.com (Clint Moore) Date: Thu Apr 30 15:02:24 2009 Subject: [Haskell-beginners] Re: List Function In-Reply-To: References: <305228b20904291925t5d1fa624s3f2e41c69cdfae4d@mail.gmail.com> <20090430034103.GA17882@seas.upenn.edu> <1241063266-sup-1450@javelin> Message-ID: <8D780AA4-6093-4BC0-9FA8-DF0A89910644@mac.com> > (Also, concerning terminology, sequence evaluates each monadic > action. > You can't evaluate a monad, it's a type constructor, not a function or > value.) Ah ha! I'm sure that it has been pointed out in some of the books that I have read, but for some reason reading that made all of the pieces suddenly fit together. Thanks for that! From es at ertes.de Thu Apr 30 16:11:52 2009 From: es at ertes.de (Ertugrul Soeylemez) Date: Thu Apr 30 15:57:44 2009 Subject: [Haskell-beginners] Re: Simplifying a 'split' function References: <50DB0726-A0D4-4832-96E1-4D7E5DDA2CFE@gmail.com> <71F1B74B-7820-4029-894C-104024BA07E0@ece.cmu.edu> Message-ID: <20090430221152.62809e65@tritium.xx> "Brandon S. Allbery KF8NH" wrote: > >> How about map pure. I do like the robot monkey though :) > > > > What is 'map pure'? > > It uses the applicative functor (Control.Applicative) instance for > lists, just as "fmap return" uses the monad instance. Both work out > to the same thing. In fact, I'd choose a combination of both, split = fmap pure which seems to be most elegant to me. It's more general than both of them. I just took 'return' instead of 'pure', because you don't need any extra modules for that. Greets, Ertugrul. -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://blog.ertes.de/