[Haskell-cafe] \Statically checked binomail heaps?
Hi, first of all this post is literate haskell I'm trying to implement a binomial heaps from okaski's book [1] but as most it's possible to be statically checked for correctness of definition. Remark that binomial heap is list of binomial trees in increasing order of rank and binomial heap of rank r is a node with r child t_1..t_r, where each t_i is binomial tree of rank r - i First I need some langue extension {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE ScopedTypeVariables #-} module BinTree where second type-level Nats and Bools, and Void i some kind of Top for Nats data Z data S a data Void data True data False Ok, let define some nice types ;) OrdLList is list of decreasing collections parametrised by type of element and length with is also highest rank of elements plus one, they are heterogeneous by they ranks type Forest = OrdLList BinTree data OrdLList (t :: * - * - * ) a :: * - * where LNil :: OrdLList t a Z LCons :: t a n - OrdLList t a n - OrdLList t a (S n ) Binomial tree is here, a I know i can't check statically an heap property data BinTree a :: * - * where Node :: Ord a = a - Forest a n - BinTree a n Heap is very similar to Forest just reversed order data OrdGList (t :: * - * - * ) a :: * - * where GNil :: OrdGList t a Void GCons :: Lt n m ~ True = t a n - OrdGList t a m - OrdGList t a n type Heap a n = OrdGList BinTree a n Predicate for testing order in Heap type family Lt a b type instance Lt Z (S a) = True type instance Lt (S a) Z = False type instance Lt (S a) (S b) = Lt a b type instance Lt a Void = True reflection form type-level nats to Int class TNum a where toNum :: a - Int instance TNum Z where toNum _ = 0 instance TNum a = TNum (S a) where toNum _ = 1 + toNum (undefined :: a) rank of binomial tree rank :: TNum n = BinTree a n - Int rank t = toNum $ undefined `asTypeOf` (getN t) getN :: t a n - n getN _ = undefined :: n root of binomial trees root :: BinTree e n - e root (Node x _ ) = x And finally first of quite serious function linking two trees with must have the same ranks, giving trees with rank greater by one link :: Ord a = BinTree a n - BinTree a n - BinTree a (S n) link t1@(Node x c1) t2@(Node y c2) | x = y = Node x $ LCons t2 c1 | otherwise = Node y $ LCons t1 c2 some simple trees for tests h = GCons t3 $ GCons t GNil t = link t1 t2 t1 = Node 3 LNil t2 = Node 2 LNil t3 = Node 5 LNil And sadly that's all I can write... for full functionality these data structure should have merge, insert, deleteMin, findMin, defined in [1] as fallow insTree t [] = [t] insTree t ts@(t':ts') | rank t rank t' = t : ts | otherwise = insTree (link t t') ts' insert x = insTree (Node 0 x []) -- in [1] rank's are write explicit in nodes merge ts [] = ts merge [] ts = ts merge ts1@(t1:ts1') ts2@(t2:ts2') | rank t1 rank t2 = t1 : merge ts1' ts2 | rank t1 rank t2 = t2 : merge ts1 ts2' | otherwise = insTree (link t1 t2) $ merge ts1' ts2' removeMinTree [] = error empty removeMinTree [t] = (t,[] removeMinTree (t:ts) | root t root t' = (t,ts) | otherwise = (t',t:ts') where (t',ts') = removeMinTree ts findMin = root . fst . removeMinTree deleteMin ts = merge (rev ts1, ts2) where (Node _ x ts1,ts2) = removeMinTree I try with all this function and with all I have problems with types the types of insTree in my opinion should be sth like: insTree :: (Min n m ~ k,TNum n, TNum m) = BinTree a n - Heap a m - Heap a k where Min looks like: type family Min a b type instance Min a Z = Z type instance Min Z a = Z type instance Min (S a) (S b) = S (Min a b) but this won't compile, ghc don't see that k can be the same type as m in first pattern, problems with rest of function was similar exclude removeMinTree with I have no idea what type it should have... Have anyone an idea how make this code working? Any help will be appreciated [1] Purely Functional Data Structures by Chris Okasaki. Cambridge University Press, 1998. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Happstack + network package issue on the Mac
On Sat, Oct 10, 2009 at 15:13, Duncan Coutts wrote: From what Gregory and Anton have said, it sounds like the SockAddr6, HostAddress6 constructors should always be available, but that using them with the socket functions should fail at runtime on platforms with no IPv6 support, or when IPv6 support is turned off for some reason. That would probably make it rather easier to have portable programs that can optionally use IPv6. Having to use TH to test at compile time if a constructor is or is not exported from another package is more than a little unpleasant. +1 Sean ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Lecture Notes Advanced Functional programming available
I am happy to announce that the rworked lecture notes for the 6th Advance Functional programming summer school have become available. Thanks, Doaitse. • Johan Jeuring (Utrecht University, NL): Libraries for Generic Programming in Haskell An extended version of this article is available as a technical report: http://www.cs.uu.nl/research/techreps/UU-CS-2008-025.html It introduces the concepts of datatype-generic programming using the libraries LIGD, SYB, and EMGM and compares them. There's also an additional section not in the published lecture notes on type-indexed datatypes with type families. You can even do the exercises in the lecture notes and check out the solutions in the tech report. Regards, Sean ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Too much strictness in binary-0.5.0.2
On Sat, 2009-09-19 at 00:36 +0400, Khudyakov Alexey wrote: Hello I run into problems with new binary package. Following function reads a list of elements one by one until end of stream. List is very long (won't fit into memory). Sorry for the late reply. In binary-0.5.0.1 and earlier it read list lazily. Now it seems that it tries to read whole list to memory. Program does not produce any output and memory usage steadily grows. Yes. We decided that having the Get monad as a lazy state monad just doesn't make sense. It makes this one use case work, but causes more problems generally. Certainly we need to be able to do lazy binary deserialisation too, but our feeling is that it should be more explicit and integrate better with error handling. Using a lazy state monad gives us neither. getStream :: Get a - Get [a] getStream getter = do empty - isEmpty if empty then return [] else do x - getter xs - getStream getter return (x:xs) How could I add laziness to this function to revert to old behavior. You can make it explicitly lazy using something like: getStream :: Get a - BS.ByteString - [a] getStream getter bs = unfoldr step (bs, 0) where step (bs, off) = case runGetState getOne bs off of (Nothing, _, _ ) - Nothing (Just x, bs', off') - Just (x, (bs', off')) getOne = do empty - isEmpty if empty then return Nothing else fmap Just getter Note the distinct lack of error handling, but if we had runGetState return an Either then you could still make this code lazy, but you'd have to decide what to do when you got a decoding error. You could at this point translate it into a pure error, or enrich your output stream type to account for the possibility of errors. Note also that if we changed runGetState to do any error handling that this would also break the lazy state monad properties that you were previously relying upon. Duncan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Documentation (was: ANN: text 0.5, a major revision of the Unicode text library)
Hi John, On Sun, Oct 11, 2009 at 14:58, John Lato wrote: For anyone writing introductions to generic programming, take this as a plea from Haskellers everywhere. If one of the RWH authors can't understand how to make use of these techniques, what hope do the rest of us have? I would like to help you with this problem, though with a different library. You can find EMGM [1] on Hackage. If you have a problem with the documentation there, please let me know. I would consider it a bug. To understand it, however, you should consider reading the tech report Libraries for Generic Programming in Haskell [2], an extended version of an article in a recently published collection of lecture notes from the 2008 Advanced Functional Programming Summer School [3]. [1] http://hackage.haskell.org/package/emgm [2] http://www.cs.uu.nl/research/techreps/UU-CS-2008-025.html [3] http://www.springerlink.com/content/978-3-642-04651-3 I agree that a lot more documentation could help, but I hope this helps. Regards, Sean ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Too much strictness in binary-0.5.0.2
Yes. We decided that having the Get monad as a lazy state monad just doesn't make sense. It makes this one use case work, but causes more problems generally. Certainly we need to be able to do lazy binary deserialisation too, but our feeling is that it should be more explicit and integrate better with error handling. Using a lazy state monad gives us neither. This is valid point. I think I'll just use variant with explicit laziness. Note also that if we changed runGetState to do any error handling that this would also break the lazy state monad properties that you were previously relying upon. I'd appreciate addition of error handling very much. Currently I have to use ErrorT and do checks by hands. I have very simple parsers so it's possible. It's not possible to do such things in general. Trading laziness for error handling is good thing I believe. At the moment it's hard to decode possibly malformed data. On 10/17/09, Duncan Coutts duncan.cou...@googlemail.com wrote: On Sat, 2009-09-19 at 00:36 +0400, Khudyakov Alexey wrote: Hello I run into problems with new binary package. Following function reads a list of elements one by one until end of stream. List is very long (won't fit into memory). Sorry for the late reply. In binary-0.5.0.1 and earlier it read list lazily. Now it seems that it tries to read whole list to memory. Program does not produce any output and memory usage steadily grows. Yes. We decided that having the Get monad as a lazy state monad just doesn't make sense. It makes this one use case work, but causes more problems generally. Certainly we need to be able to do lazy binary deserialisation too, but our feeling is that it should be more explicit and integrate better with error handling. Using a lazy state monad gives us neither. getStream :: Get a - Get [a] getStream getter = do empty - isEmpty if empty then return [] else do x - getter xs - getStream getter return (x:xs) How could I add laziness to this function to revert to old behavior. You can make it explicitly lazy using something like: getStream :: Get a - BS.ByteString - [a] getStream getter bs = unfoldr step (bs, 0) where step (bs, off) = case runGetState getOne bs off of (Nothing, _, _ ) - Nothing (Just x, bs', off') - Just (x, (bs', off')) getOne = do empty - isEmpty if empty then return Nothing else fmap Just getter Note the distinct lack of error handling, but if we had runGetState return an Either then you could still make this code lazy, but you'd have to decide what to do when you got a decoding error. You could at this point translate it into a pure error, or enrich your output stream type to account for the possibility of errors. Note also that if we changed runGetState to do any error handling that this would also break the lazy state monad properties that you were previously relying upon. Duncan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] x - String
On 10/17/09, Andrew Coppin andrewcop...@btinternet.com wrote: Derek Elkins wrote: See vacuum: http://hackage.haskell.org/package/vacuum Could be useful... Thanks! As Derek mentioned, vacuum would be perfect for this: - import Data.Word import GHC.Vacuum import GHC.Vacuum.ClosureType import qualified Data.IntMap as IM type Info = (ClosureType -- what kind of heap node is this? ,[String] -- [pkg,mod,con] for constructors ,[Int]-- pointers refering to other nodes in IntMap ,[Word]) -- literal data in constructors overview :: HNode - Info overview o = let ptrs = nodePtrs o lits = nodeLits o itab = nodeInfo o ctyp = itabType itab -- only available -- for constructors (pkg,mod,con) = itabName itab names = filter (not . null) [pkg,mod,con] in (ctyp ,names -- [] for non-data ,ptrs ,lits) -- returns an adjacency-list graph info :: a - [(Int,Info)] info = fmap (\(a,b)-(a,overview b)) . IM.toList . vacuum -- returns an adjacency-list graph infoLazy :: a - [(Int,Info)] infoLazy = fmap (\(a,b)-(a,overview b)) . IM.toList . vacuumLazy - -- example usage data A a = A Int | B a | forall b. C b [A a] val0 = [A 42, B (Left Nothing), C (pi,()) val0] val1 = fmap (\n - C n []) [0..] {- ghci mapM_ print (info val0) Loading package vacuum-1.0.0 ... linking ... done. (0,(CONSTR_2_0,[ghc-prim,GHC.Types,:],[1,2],[])) (1,(CONSTR,[main,Main,A],[3],[])) (2,(CONSTR_2_0,[ghc-prim,GHC.Types,:],[4,5],[])) (3,(CONSTR_0_1,[ghc-prim,GHC.Types,I#],[],[42])) (4,(CONSTR,[main,Main,B],[6],[])) (5,(CONSTR_2_0,[ghc-prim,GHC.Types,:],[8,9],[])) (6,(CONSTR_1_0,[base,Data.Either,Left],[7],[])) (7,(CONSTR_NOCAF_STATIC,[base,Data.Maybe,Nothing],[],[])) (8,(CONSTR,[main,Main,C],[10,0],[])) (9,(CONSTR_NOCAF_STATIC,[ghc-prim,GHC.Types,[]],[],[])) (10,(CONSTR_2_0,[ghc-prim,GHC.Tuple,(,)],[11,12],[])) (11,(CONSTR_NOCAF_STATIC,[ghc-prim,GHC.Types,D#],[],[4614256656552045848])) (12,(CONSTR_NOCAF_STATIC,[ghc-prim,GHC.Unit,()],[],[])) ghci mapM_ print (infoLazy val1) (0,(AP,[],[],[])) ghci val1 `seq` () () ghci mapM_ print (infoLazy val1) (0,(CONSTR_2_0,[ghc-prim,GHC.Types,:],[1,2],[])) (1,(THUNK_2_0,[],[],[])) (2,(THUNK_2_0,[],[],[])) ghci length . take 2 $ val1 2 ghci mapM_ print (infoLazy val1) (0,(CONSTR_2_0,[ghc-prim,GHC.Types,:],[1,2],[])) (1,(THUNK_2_0,[],[],[])) (2,(CONSTR_2_0,[ghc-prim,GHC.Types,:],[3,4],[])) (3,(THUNK_2_0,[],[],[])) (4,(THUNK_2_0,[],[],[])) ghci case val1 of a:b:_ - a `seq` b `seq` () () ghci mapM_ print (infoLazy val1) (0,(CONSTR_2_0,[ghc-prim,GHC.Types,:],[1,2],[])) (1,(CONSTR,[main,Main,C],[3,4],[])) (2,(CONSTR_2_0,[ghc-prim,GHC.Types,:],[5,6],[])) (3,(CONSTR_0_1,[integer,GHC.Integer.Internals,S#],[],[0])) (4,(CONSTR_NOCAF_STATIC,[ghc-prim,GHC.Types,[]],[],[])) (5,(CONSTR,[main,Main,C],[7,4],[])) (6,(THUNK_2_0,[],[],[])) (7,(CONSTR_0_1,[integer,GHC.Integer.Internals,S#],[],[1])) -} - Matt ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Merging modules (again)
Hi, I have tried qualified imports, synonyms and newtypes but still I could not implement the merging task (previously posted). This is probably because I have little knowledge of Haskell *or* the task is not really suited to Haskell (more of a specification task than a programming task). My main questions are; Can the merging task be achieved using the Haskell module system? I also posted a question on how this task could be done using type classes. I would ask the same question with respect to type classes. Regards, Pat pat browne wrote: Hi, I want to establish the strengths and weakness of the Haskell module system for the ontology merging task (I know it was not designed for this!). I wish to make a new module (MERGEDONTOLOGY) from three input modules one of which is common to the other two. The desired merge should contain the following data types: Woman FinancialBank HumanBeing RiverBank Which are all identifiable without any qualifying module names. Below is the detailed requirement and my first attempt at this task in Haskell. I would be grateful for any information on how to merge these modules giving a set of unique unqualified types (i.e. without reference to their originating modules). Regards, Pat Informal Specification The diagram and text below explain the requirement MERGEDONTOLOGY { Woman, RiverBank, FinancialBank, HumanBeing} /\ /\ / \ /\ / \ / \ / \ / \ ONTOLOGY1 ONTOLOGY2 {Woman, Bank, Person} {Woman, Bank, Human} /\ /\ \ / \ / \ / \ / \ / \ / \ / {Woman , Person} COMMMON This example includes both synonyms and homonyms. 1)The Woman sort (or data type) should be the same in all modules, there is only one Woman sort and it is named as such in each module. Hence there should be only one MERGEDONTOLOGY.Woman. 2)There is only one sort MERGEDONTOLOGY.HumanBeing, but there are 3 synonyms for it called ONTOLOGY2.Human, ONTOLOGY1.Person, and COMMON.Person. The last sentence considers ONTOLOGY1.Person and COMMON.Person as synonyms; they have different qualifiers but the intention is that they represnt the same thing. Hence should be mapped to same MERGEDONTOLOGY.HumanBeing. To do this (in Maude) COMMON.Person was renamed to ONTOLOGY2.Human which in turn was renamed to MERGEDONTOLOGY.HumanBeing. 3)The homonyms are ONTOLOGY1.Bank and ONTOLOGY2.Bank should become distinct sorts MERGEDONTOLOGY.RiverBank and MERGEDONTOLOGY.FinancialBank in the final ontology at the top of the diagram. My first attemt at merging using Haskell modules = module COMMON where data Woman = WomanC data Person = PersonC module ONTOLOGY1 where import COMMON data Bank = BankC module ONTOLOGY2 where import COMMON data Bank = BankC module MERGEDONTOLOGY where import ONTOLOGY1 import ONTOLOGY2 If I use qualified names all the constructors are interpreted correctly MERGEDONTOLOGY :t COMMON.WomanC COMMON.WomanC :: COMMON.Woman MERGEDONTOLOGY :t COMMON.PersonC COMMON.PersonC :: COMMON.Person MERGEDONTOLOGY :t ONTOLOGY2.BankC ONTOLOGY2.BankC :: ONTOLOGY2.Bank MERGEDONTOLOGY :t ONTOLOGY1.BankC ONTOLOGY1.BankC :: ONTOLOGY1.Bank MERGEDONTOLOGY :t COMMON.Woman However, I wish that these types and constructors be fully defined in the context of the MERGEDONTOLOGY. I have tried type synonyms and newtypes. type RiverBank = ONTOLOGY1.Bank type FinancialBank = ONTOLOGY2.Bank newtype RiverBank = BankC Int I have not explored import modes or qualified imports. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Too much strictness in binary-0.5.0.2
On Sun, 2009-10-18 at 19:53 +0400, Alexey Khudyakov wrote: Yes. We decided that having the Get monad as a lazy state monad just doesn't make sense. It makes this one use case work, but causes more problems generally. Certainly we need to be able to do lazy binary deserialisation too, but our feeling is that it should be more explicit and integrate better with error handling. Using a lazy state monad gives us neither. This is valid point. I think I'll just use variant with explicit laziness. Note also that if we changed runGetState to do any error handling that this would also break the lazy state monad properties that you were previously relying upon. I'd appreciate addition of error handling very much. Currently I have to use ErrorT and do checks by hands. I have very simple parsers so it's possible. It's not possible to do such things in general. Trading laziness for error handling is good thing I believe. At the moment it's hard to decode possibly malformed data. It's possible to have both error handling and lazyness by extending the result to include the representation of the errors. Duncan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Lecture Notes Advanced Functional programming available
$83 and 3-4 weeks for a 300 page book? Oy vey. Warren On Fri, Oct 16, 2009 at 7:24 AM, S. Doaitse Swierstra doai...@swierstra.net wrote: I am happy to announce that the rworked lecture notes for the 6th Advance Functional programming summer school have become available. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Error handling package
While working on the next release of data-object, I wanted to represent some operations that might fail. The typical candidates were: 1) Maybe 2) Either 3) Monad Monad is always iffy because of the often times poorly defined fail. Maybe doesn't provide any means of reporting what the problem was. Either is not defined as a Monad in the base library. Also, the usual candidate of Either String only provides for an error message. It would be nice to have more in-depth information available. So I've put together a package I call attempt. It defines a data type called (surprise) Attempt with a Success and Failure constructor. The trick here is that it using the new extensible exceptions under the surface, so you can report any kind of exception you want. It also provides a FromAttempt type class for possible conversion targets from an Attempt, provides an attempt function with some helpers for performing the equivalent of Control.Exception.catches, and provides two samples of functions I would want to implement with this library: attemptJoin and attemptLookup. My questions for the list are: 1) Is the overall approach sound, or do people have better ideas? 2) Are there any other FromAttempt instances I should provide out of the box? 3) I was considering adding specialized versions of the fromAttempt function, ie ioFromAttempt, maybeFromAttempt. Thoughts? 4) Should I follow the naming scheme attemptJoin, attemptLookup, etc, or just call the functions join, lookup and force people to import the module qualified? 5) Any other suggestions for attempt functions? I've considered head/tail/etc. 6) Include ToAttempt? The code is available on github at http://github.com/snoyberg/attempt/blob/master/Data/Attempt.hs . I appreciate the review. Also, I have not yet documented the code, but I will do so before uploading to Hackage; I just didn't want to document a changing target. Thank you, Michael ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Error handling package
On Sun, 18 Oct 2009, Michael Snoyman wrote: While working on the next release of data-object, I wanted to represent some operations that might fail. The typical candidates were: 1) Maybe 2) Either 3) Monad Monad is always iffy because of the often times poorly defined fail. Maybe doesn't provide any means of reporting what the problem was. Either is not defined as a Monad in the base library. Also, the usual candidate of Either String only provides for an error message. It would be nice to have more in-depth information available. So I've put together a package I call attempt. It defines a data type called (surprise) Attempt with a Success and Failure constructor. Does the explicit-exception package provide what you need? http://hackage.haskell.org/package/explicit-exception ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: [Haskell-beginners] map question
Gregory Propf gregorypropf at yahoo.com writes: I actually meant it as sort of a joke but maybe it's not after all. Seriously though, using anything non-ASCII in source code is a bad idea, because there are lots of fonts and editors in the world. It seems natural to me to have (`-`2) stand for (flip (-) 2), if only that would be made legal syntax, just as (`foldl`0) stands for (flip (foldl) 0). Supposedly there is no reason to write (`:`[]) since : is already an infix operator, but making it a no-op wouldn't hurt, and would give us a benefit of being able finally to write the binary-minus flip-section in a visually apparent way. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: [Haskell-beginners] map question
On Sun, Oct 18, 2009 at 4:47 PM, Will Ness will_...@yahoo.com wrote: Gregory Propf gregorypropf at yahoo.com writes: I actually meant it as sort of a joke but maybe it's not after all. Seriously though, using anything non-ASCII in source code is a bad idea, because there are lots of fonts and editors in the world. It seems natural to me to have (`-`2) stand for (flip (-) 2), if only that would be made legal syntax, just as (`foldl`0) stands for (flip (foldl) 0). Or you could use the subtract function. map (subtract 2) [3,4,5] [1,2,3] I don't think syntax sugar is worth it in this case. Luke ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Error handling package
(Sorry, accidently took off cafe.) On Mon, Oct 19, 2009 at 12:44 AM, Henning Thielemann lemm...@henning-thielemann.de wrote: On Mon, 19 Oct 2009, Michael Snoyman wrote: Does the explicit-exception package provide what you need? http://hackage.haskell.org/package/explicit-exception I don't think so, but correct me if I'm wrong. I want to make it easy to chain together computations which could fail in different ways. For example, something like this: attemptReadInt :: String - Attempt Int attemptLookup :: String - [(String, String)] - Attempt String attemptLookupInt :: String - [(String, String)] - Attempt Int attemptLookupInt k m = attemptLookup k m = attemptReadInt Now, in the explicit-exception package, I could- in this simple example- define something like: data MyErrors = KeyNotFound | InvalidInt type Attempt = Exceptional MyErrors True; that's what I meant by I could do this in my simple example. But this solution would not scale. You want to add other exceptions? The idea of my package is to make exceptions explicit in the type. Otherwise you would use extensible-exceptions. Or you could define MyErrors using an existential type. Which is my point. I'm trying to provide a package for non-explicit exceptions. To compare to other programming languages, I think your package is providing the equivalent of Java checked exceptions, while mine is providing (safe) unchecked exceptions. I say safe because you still need to explicitly decide to turn an Attempt into a possible runtime exception which will bring down your program. Defining MyErrors using an existential type would essentially recreate the entire attempt package; I don't see that purpose in everyone wanted unchecked exceptions needing to reinvent the wheel in non-compatible ways. If multiple libraries use attempt, they can easily have their possible-error-returning functions chain together safely. Additionally, there's two immediate features I think I would miss from my package: 1) fail works properly, so an Attempt would be a valid monad response from people who use that function. As far as I understand, 'fail' is used/abused for reporting failed pattern matches in do notation. If a failed pattern match indicates a programming error, it should be a really error, and not something that must be handled at run-time. That's a lot of very debateable statements you just made. It might be that it's strongly encouraged to only use fail for failed pattern matching, but in practice you could use it for any monadic failure. Also, there's nothing stopping a user from re-throwing pattern match exceptions received in an Attempt. Michael ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: [Haskell-beginners] map question
Luke Palmer lrpalmer at gmail.com writes: Or you could use the subtract function. map (subtract 2) [3,4,5] [1,2,3] I don't want to. I don't think syntax sugar is worth it in this case. I do. Operators are great because they make our intent visible, immediately apparent. Long words' meaning, like subtract's, is not immediately apparent, and they break consistency. Not everyone's first language in life was English, you see. (`foldl`2) works. (`-`2) should too. I'll settle for (+(-2)) for now, but it ain't that pretty. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Problems with Haskell
Before anything else, I want to point out that I have no intention to confront your community, or denigrate Haskell. A few days ago I answered an email from a Clean programmer on something related to Clean. He was worried that Clean team could give up its good work, and Clean could disappear; therefore, he was thinking about switching to Haskell. Since I thought that my email could be of interest for the Clean community, I posted it in the -- small-- Clean list :-(Clean is not as popular as Haskell). I received a lot of furious and offensive private emails for suggesting the Clean programmer to stick with Clean. However, I also received a very polite, humorous, and illuminating private email from a person who seems to work at Microsoft. His name is Simon Peyton-Jones. He urged me to post my comments on a Haskell cafe. He also filed one of my comments as a bug in a Haskell bug track. Here is a couple of snippets from his email: --- I think it's v bad that a straightforward program runs so slowly, and it's certainly true that this is an area we could pay more attention to. --- Meanwhile, I'm curious: are the arrays in Philippos's program strict? Or lazy? If strict, that's a pretty big difference. Therefore, here are my comments, with a lot of code. A few months ago I came accross an unpublished article about a novel genetic programming system. The system was coded in Larceny Scheme. I translated it to Clean and to Haskell. Unhappily, I cannot post the program here because it is very large, and the authors of the original Lisp program don't want me to divulge it before they see in in a printed page of a Journal. Therefore, I wrote an empty genetic programming framework, just to compare languages. Comparing Clean and Haskell, I noticed: 1 -- Clean compiler almost never let me do very stupid things, like trying to unbox a tree, or to write in a closed file (I will post an example of this in a near future). For instance, Clean compiler would never swallow something like the code below: import Control.Monad.ST import Data.Array.ST import Data.Array.Base import System.Random data Op = AND | OR | NOT; data Tree= L Double | T Op [Tree] main = print $ runST (do arr - newArray (1,200) (L 0.0) :: ST s (STArray s Int Tree) go arr 200 0.0 ) go :: STArray s Int Tree - Int - Double - ST s Double go a i acc | i 1 = return acc | otherwise=do b - unsafeRead a i {- readArray a i -} writeArray a i (setDouble ((getDouble b)+3.0)) c - readArray a i go a (i-1) (acc+ (getDouble c)) -- What I really need is a random index in Haskell. getDouble (L r)= r getDouble _ = 0.0 setDouble r= L r 2 -- Safety does not cost much in Clean. For instance, removing array boundary check does not seem to affect Clean. I believe that it does not affect Haskell either, but I have not verified this point. 3 -- Haskell seems to loop more often than Clean. For instance, Haskell may loop if I change function mutate to mutate e (L i) xs = (e, xs) mutate e t (y:ys) = ins t (rnLen t y, ys) where ins (T p (L i:xs)) (0, st)=(T p (e:xs), st) ins (T p (t:xs)) (n,(r1:rs)) | n 0= let (T p mt, s2)= ins (T p xs)(n-1, rs) in (T p (t:mt), s2) ins (T p (t:xs)) (n,(r1:rs)) | rn 2 r1== 0= (T p (e:xs), rs) | rn 2 r1== 1= let (xpr, st)= mutate e t rs in (T p (xpr:xs), st) This might be a bug in my implementation of show Tree. It would be great if you people could show me what I did wrong. 4 -- On the plus side, there are libraries in Haskell that seem to behave better than the Clean equivalent libraries. This could be explained by the fact that there are a lot of people coding Haskell libraries, while Clean team seems to be reluctant in accepting libraries from outsiders. For instance, lethevert made a very important improvement in ObjectIO (changing fonts in edit text field), but it was never incorporated into Clean (yes, I wrote a lot of emails to Clean team about it). Last year, when I was learning Clean, I discovered that many of my professors and teachers are presbyopic. Therefore, it would be a good policy to use very large fonts for homework. I only succeeded in doing it thanks to lethevert. In the case of the program below, Haskell System.Random library seems to work much better than Clean MersenneTwister. 5 --- Any improvement in the program below will be welcome. The program is already very fast thanks to suggestions I received from the bug track people, and from Peyton-Jones. Function show seems to loop if I replace mutate in item 3 for mutate in the code below. {- ghc gp.hs -O2 --make -} {- Execute: gp.exe +RTS -sstderr -} import Control.Monad.ST import Data.Array.ST import Data.Array.Base import System.Random data Op = AND | OR | NOT; data Tree= L Int | T Op [Tree] psz= 2
Re: [Haskell-cafe] Re: [Haskell-beginners] map question
Will Ness wrote: Luke Palmer lrpalmer at gmail.com writes: Or you could use the subtract function. map (subtract 2) [3,4,5] [1,2,3] I don't want to. I don't think syntax sugar is worth it in this case. I do. Operators are great because they make our intent visible, immediately apparent. Long words' meaning, like subtract's, is not immediately apparent, and they break consistency. Not everyone's first language in life was English, you see. I'm with Luke on this one. It's a shame that negation uses the same symbolic identifier as subtraction, but introducing this new sugar only serves to make things more complex than they already are. If anything, negation should be moved to using a different identifier to remove the current ambiguity (as is done in some other languages). (`foldl`2) works. (`-`2) should too. The `` syntax is for converting lexical identifiers into infix operators. Symbolic identifiers are already infix, which is why `` doesn't work for them. If we introduced this then those striving for consistency would be right in requesting that this pattern be allowed for all symbolic operators. I for one am opposed to introducing superfluous syntax for duplicating the current ability to write things in the same ways. Attack the underlying problem, don't introduce hacks to cover up broken hacks. This isn't C++. -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] How to use bracket properly ?
winSSQ count noRed noBlue = do { yesRed - [1..33] \\ noRed; yesBlue - [1..16] \\ noBlue; bracket (openFile ssqNum.txt WriteMode) (hClose) (\hd1 - pickSSQ count yesRed yesBlue hd1); return () } will report: Couldn't match expected type `IO ()' against inferred type `[()]' In a stmt of a 'do' expression: bracket (openFile ssqNum.txt WriteMode) (hClose) (\ hd1 - pickSSQ count yesRed yesBlue hd1) However, the following works fine: winSSQ count noRed noBlue = do let yesRed = [1..33] \\ noRed let yesBlue = [1..16] \\ noBlue bracket (openFile ssqNum.txt WriteMode) (hClose) (\hd1 - pickSSQ count yesRed yesBlue hd1) Why ? -- View this message in context: http://www.nabble.com/How-to-use-%22bracket%22-properly---tp25953522p25953522.html Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] How to use bracket properly ?
They're in different Monads. The first one does x - [...], which means that you're operating in the list Monad instance, and bracket operates in the IO Monad. The second one uses let x = [...] which doesn't have any effect on what Monad you're in, so the whole thing can be in IO. Note that when you do x - [1..3]; y - [4..6] you're going to get all 9 pairs of values from x and y, by the way. Hope this helps, Dan On Mon, Oct 19, 2009 at 1:33 AM, zaxis z_a...@163.com wrote: winSSQ count noRed noBlue = do { yesRed - [1..33] \\ noRed; yesBlue - [1..16] \\ noBlue; bracket (openFile ssqNum.txt WriteMode) (hClose) (\hd1 - pickSSQ count yesRed yesBlue hd1); return () } will report: Couldn't match expected type `IO ()' against inferred type `[()]' In a stmt of a 'do' expression: bracket (openFile ssqNum.txt WriteMode) (hClose) (\ hd1 - pickSSQ count yesRed yesBlue hd1) However, the following works fine: winSSQ count noRed noBlue = do let yesRed = [1..33] \\ noRed let yesBlue = [1..16] \\ noBlue bracket (openFile ssqNum.txt WriteMode) (hClose) (\hd1 - pickSSQ count yesRed yesBlue hd1) Why ? -- View this message in context: http://www.nabble.com/How-to-use-%22bracket%22-properly---tp25953522p25953522.html Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe