Re: [Haskell-cafe] What class for splittable data / balanced-fold?
On Sun, Sep 29, 2013 at 9:13 PM, Ryan Newton rrnew...@gmail.com wrote: Thanks, that's interesting to know (re: Fortress). Interestingly, in my Fortress days we looked at both using a split-like interface and at a more foldMap / reduce - like interface, and it seemed like the latter worked better – it requires a lot less boilerplate for controlling recursion, and better matches the fanout of whatever structure you're actually using underneath. Ok, we'll have to try that. I may be underestimating the power of a newtype and a monoid instance to expose the structure.. I was wrong about this before [1]. Here's the foldMap instance for Data.Map: foldMap _ Tip = mempty foldMap f (Bin _ _ v l r) = Foldable.foldMap f l `mappend` f v `mappend` Foldable.foldMap f r Simon Marlow in his recent Haxl talk also had a domain where they wanted a symmetric (non-monadic) parallel spawn operation... But it remains pretty hard for me to reason about the operational behavior of these things... especially since foldMap instances may vary. I'll note that there's really a documentation responsibility here that hasn't been honored as much as it should (possibly because lots of folks are driving Foldable, which other commenters have noted doesn't seem to do what you want for tree-like data structures – I certainly didn't realize that). It'd be worth thinking about doing the derivation of foldMap directly from the structure of the underlying type. It'd also be worth documenting when we get tree-structured traversal out of a Foldable instance, and fixing the ones that don't provide it. And I agree that getting down to non-allocating traversals is the ultimate goal here. If we leak space or lose parallelism we might as well not bother. -Jan Thanks, -Ryan [1] For example, here is a non-allocating traverseWithKey_ that I failed to come up with: -- Version of traverseWithKey_ from Shachaf Ben-Kiki -- (See thread on Haskell-cafe.) -- Avoids O(N) allocation when traversing for side-effect. newtype Traverse_ f = Traverse_ { runTraverse_ :: f () } instance Applicative f = Monoid (Traverse_ f) where mempty = Traverse_ (pure ()) Traverse_ a `mappend` Traverse_ b = Traverse_ (a * b) -- Since the Applicative used is Const (newtype Const m a = Const m), the -- structure is never built up. --(b) You can derive traverseWithKey_ from foldMapWithKey, e.g. as follows: traverseWithKey_ :: Applicative f = (k - a - f ()) - M.Map k a - f () traverseWithKey_ f = runTraverse_ . foldMapWithKey (\k x - Traverse_ (void (f k x))) foldMapWithKey :: Monoid r = (k - a - r) - M.Map k a - r foldMapWithKey f = getConst . M.traverseWithKey (\k x - Const (f k x)) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What class for splittable data / balanced-fold?
Oops, this email got stuck in the pipe (flaky internet): foldMap _ Tip = mempty foldMap f (Bin _ _ v l r) = Foldable.foldMap f l `mappend` f v `mappend` Foldable.foldMap f r Btw, from my perspective, one problem with relying on foldMap is that it treats the whole structure uniformly, whereas the split approach would let one, for example, bottom out to a sequential implementation at a certain granularity. Perhaps that is the boilerplate for controlling recursion that you referred to... but isn't it sometimes necessary? -Ryan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What class for splittable data / balanced-fold?
I've got a Partitionable class that I've been using for this purpose: https://github.com/mikeizbicki/ConstraintKinds/blob/master/src/Control/ConstraintKinds/Partitionable.hs The function called parallel in the HLearn library will automatically parallelize any homomorphism from a Partionable to a Monoid. I specifically use that to parallelize machine learning algorithms. I have two thoughts for better abstractions: 1) This Partitionable class is essentially a comonoid. By reversing the arrows of mappend, we get: comappend :: a - (a,a) By itself, this works well if the number of processors you have is a power of two, but it needs some more fanciness to get things balanced properly for other numbers of processors. I bet there's another algebraic structure that would capture these other cases, but I'm not sure what it is. 2) I'm working with parallelizing tree structures right now (kd-trees, cover trees, oct-trees, etc.). The real problem is not splitting the number of data points equally (this is easy), but splitting the amount of work equally. Some points take longer to process than others, and this cannot be determined in advance. Therefore, an equal split of the data points can result in one processor getting 25% of the work load, and the second processor getting 75%. Some sort of lazy Partitionable class that was aware of processor loads and didn't split data points until they were needed would be ideal for this scenario. On Sat, Sep 28, 2013 at 6:46 PM, adam vogt vogt.a...@gmail.com wrote: On Sat, Sep 28, 2013 at 1:09 PM, Ryan Newton rrnew...@gmail.com wrote: Hi all, We all know and love Data.Foldable and are familiar with left folds and right folds. But what you want in a parallel program is a balanced fold over a tree. Fortunately, many of our datatypes (Sets, Maps) actually ARE balanced trees. Hmm, but how do we expose that? Hi Ryan, At least for Data.Map, the Foldable instance seems to have a reasonably balanced fold called fold (or foldMap): fold t = go t where go (Bin _ _ v l r) = go l `mappend` (v `mappend` go r) This doesn't seem to be guaranteed though. For example ghc's derived instance writes the foldr only, so fold would be right-associated for a: data T a = B (T a) (T a) | L a deriving (Foldable) Regards, Adam ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What class for splittable data / balanced-fold?
On Sat, Sep 28, 2013 at 1:09 PM, Ryan Newton rrnew...@gmail.com wrote: Hi all, We all know and love Data.Foldable and are familiar with left folds and right folds. But what you want in a parallel program is a balanced fold over a tree. Fortunately, many of our datatypes (Sets, Maps) actually ARE balanced trees. Hmm, but how do we expose that? It seems like it would be nice to have a* standard class t*hat allows you to split a datatype into roughly even halves, until you get down to the leaves. This goes along with Guy Steele's argument that we should use append lists as primitive rather than cons-lists, and it's why we added append-lists within the monad-par libraryhttp://hackage.haskell.org/package/monad-par-extras-0.3.3/docs/Control-Monad-Par-AList.html . Interestingly, in my Fortress days we looked at both using a split-like interface and at a more foldMap / reduce - like interface, and it seemed like the latter worked better – it requires a lot less boilerplate for controlling recursion, and better matches the fanout of whatever structure you're actually using underneath. So I'd just go with a hand-written Foldable instance here. But I'd love to hear if you've come up with an application that requires split itself, and that *isn't* zip. I recall we decided zip was better done with element-and-index iteration over one of the structures and indexing into the other since most tree structures don't actually zip properly anyway. -Jan-Willem Maessen ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What class for splittable data / balanced-fold?
Thanks, that's interesting to know (re: Fortress). Interestingly, in my Fortress days we looked at both using a split-like interface and at a more foldMap / reduce - like interface, and it seemed like the latter worked better – it requires a lot less boilerplate for controlling recursion, and better matches the fanout of whatever structure you're actually using underneath. Ok, we'll have to try that. I may be underestimating the power of a newtype and a monoid instance to expose the structure.. I was wrong about this before [1]. Here's the foldMap instance for Data.Map: foldMap _ Tip = mempty foldMap f (Bin _ _ v l r) = Foldable.foldMap f l `mappend` f v `mappend` Foldable.foldMap f r Simon Marlow in his recent Haxl talk also had a domain where they wanted a symmetric (non-monadic) parallel spawn operation... But it remains pretty hard for me to reason about the operational behavior of these things... especially since foldMap instances may vary. Thanks, -Ryan [1] For example, here is a non-allocating traverseWithKey_ that I failed to come up with: -- Version of traverseWithKey_ from Shachaf Ben-Kiki -- (See thread on Haskell-cafe.) -- Avoids O(N) allocation when traversing for side-effect. newtype Traverse_ f = Traverse_ { runTraverse_ :: f () } instance Applicative f = Monoid (Traverse_ f) where mempty = Traverse_ (pure ()) Traverse_ a `mappend` Traverse_ b = Traverse_ (a * b) -- Since the Applicative used is Const (newtype Const m a = Const m), the -- structure is never built up. --(b) You can derive traverseWithKey_ from foldMapWithKey, e.g. as follows: traverseWithKey_ :: Applicative f = (k - a - f ()) - M.Map k a - f () traverseWithKey_ f = runTraverse_ . foldMapWithKey (\k x - Traverse_ (void (f k x))) foldMapWithKey :: Monoid r = (k - a - r) - M.Map k a - r foldMapWithKey f = getConst . M.traverseWithKey (\k x - Const (f k x)) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] What class for splittable data / balanced-fold?
Hi all, We all know and love Data.Foldable and are familiar with left folds and right folds. But what you want in a parallel program is a balanced fold over a tree. Fortunately, many of our datatypes (Sets, Maps) actually ARE balanced trees. Hmm, but how do we expose that? It seems like it would be nice to have a* standard class t*hat allows you to split a datatype into roughly even halves, until you get down to the leaves. This goes along with Guy Steele's argument that we should use append lists as primitive rather than cons-lists, and it's why we added append-lists within the monad-par libraryhttp://hackage.haskell.org/package/monad-par-extras-0.3.3/docs/Control-Monad-Par-AList.html . Does this class exist already? A random google search brought up this module by the name Data.Splittablehttp://hackage.haskell.org/package/unfoldable-0.2.0/docs/Data-Splittable.html, but it's not quite the right thing. Thanks, -Ryan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What class for splittable data / balanced-fold?
On Sat, Sep 28, 2013 at 1:09 PM, Ryan Newton rrnew...@gmail.com wrote: Hi all, We all know and love Data.Foldable and are familiar with left folds and right folds. But what you want in a parallel program is a balanced fold over a tree. Fortunately, many of our datatypes (Sets, Maps) actually ARE balanced trees. Hmm, but how do we expose that? Hi Ryan, At least for Data.Map, the Foldable instance seems to have a reasonably balanced fold called fold (or foldMap): fold t = go t where go (Bin _ _ v l r) = go l `mappend` (v `mappend` go r) This doesn't seem to be guaranteed though. For example ghc's derived instance writes the foldr only, so fold would be right-associated for a: data T a = B (T a) (T a) | L a deriving (Foldable) Regards, Adam ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What am I missing? Cycle in type synonym declarations
GHC tries to typecheck quotations. In this case it's trying to typecheck the declaration type Bar = FooT $t Part of type checking is rejecting recursive type synonyms. Here GHC is rejecting it because it *might* be recursive, depending on how $t is filled in. The trouble is that we really *can't* typecheck partial declarations like this one. All this will be fixed when we fold in the new Template Haskell story (it'll be in 7.8). See my blog post on the GHC Trac (from about 2 yrs ago) describing the change. (I'm on a train so don't know the URL.) Geoff has made the change... it just needs to be merged in. Simon | -Original Message- | From: Haskell-Cafe [mailto:haskell-cafe-boun...@haskell.org] On Behalf Of David | Fox | Sent: 20 August 2013 22:00 | To: Haskell Cafe | Subject: [Haskell-cafe] What am I missing? Cycle in type synonym declarations | | This file gives me the error Cycle in type synonym declarations Can | anyone tell me why? I'm just trying to write a function to create a | type that is a FooT with the type parameter fixed. | | {-# LANGUAGE TemplateHaskell #-} | import Language.Haskell.TH (Q, Dec, TypeQ) | | data FooT a = FooT a | | foo :: TypeQ - Q [Dec] | foo t = [d| type Bar = FooT $t |] | | ___ | Haskell-Cafe mailing list | Haskell-Cafe@haskell.org | http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] What am I missing? Cycle in type synonym declarations
This file gives me the error Cycle in type synonym declarations Can anyone tell me why? I'm just trying to write a function to create a type that is a FooT with the type parameter fixed. {-# LANGUAGE TemplateHaskell #-} import Language.Haskell.TH (Q, Dec, TypeQ) data FooT a = FooT a foo :: TypeQ - Q [Dec] foo t = [d| type Bar = FooT $t |] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What am I missing? Cycle in type synonym declarations
Hi, In this case, you have two 'FooT' names: one is the Type and the other is the Constructor. Perhaps Template Haskell is capturing the wrong one inside the quote (probably the constructor). When you have name shadowing, you should always use a lookup function. You can find these lookup functions in the Template Haskell library. In the meantime, just for a quick test, you can try to change the name of the constructor to something else to avoid capturing, and you can see if the rest of the code works. Jose On Tue, Aug 20, 2013 at 02:00:29PM -0700, David Fox wrote: This file gives me the error Cycle in type synonym declarations Can anyone tell me why? I'm just trying to write a function to create a type that is a FooT with the type parameter fixed. {-# LANGUAGE TemplateHaskell #-} import Language.Haskell.TH (Q, Dec, TypeQ) data FooT a = FooT a foo :: TypeQ - Q [Dec] foo t = [d| type Bar = FooT $t |] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What am I missing? Cycle in type synonym declarations
On Tue, Aug 20, 2013 at 5:00 PM, David Fox d...@seereason.com wrote: This file gives me the error Cycle in type synonym declarations Can anyone tell me why? I'm just trying to write a function to create a type that is a FooT with the type parameter fixed. {-# LANGUAGE TemplateHaskell #-} import Language.Haskell.TH (Q, Dec, TypeQ) data FooT a = FooT a foo :: TypeQ - Q [Dec] foo t = [d| type Bar = FooT $t |] Hi David, That's strange considering you can accomplish the same thing with: foo t = fmap (:[]) $ tySynD (mkName Bar) [] [t| FooT $t |] Bugs like http://ghc.haskell.org/trac/ghc/ticket/4230 are a similar problem. In your case it seems that GHC is too eager to prevent the cycle you could make with foo (conT (mkName Bar))) Regards, Adam ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What am I missing? Cycle in type synonym declarations
On Tue, Aug 20, 2013 at 2:35 PM, adam vogt vogt.a...@gmail.com wrote: On Tue, Aug 20, 2013 at 5:00 PM, David Fox d...@seereason.com wrote: This file gives me the error Cycle in type synonym declarations Can anyone tell me why? I'm just trying to write a function to create a type that is a FooT with the type parameter fixed. {-# LANGUAGE TemplateHaskell #-} import Language.Haskell.TH (Q, Dec, TypeQ) data FooT a = FooT a foo :: TypeQ - Q [Dec] foo t = [d| type Bar = FooT $t |] Hi David, That's strange considering you can accomplish the same thing with: foo t = fmap (:[]) $ tySynD (mkName Bar) [] [t| FooT $t |] Bugs like http://ghc.haskell.org/trac/ghc/ticket/4230 are a similar problem. In your case it seems that GHC is too eager to prevent the cycle you could make with foo (conT (mkName Bar))) Regards, Adam Thanks Adam, this must be the answer. And thanks for the equivalent expression. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] what is wrong w my IORef Word32 ?
All, what is wrong w the below code? I get an type error related to the operation shiftL import Data.Bits import Data.Word import Data.IORef data Word32s = Word32s { x :: IORef Word32 } bitfield :: Word32 bitfield = 0 mkbitfield :: Word32 - IO Word32s mkbitfield i = do the_bf - newIORef i return (Word32s the_bf) sLbitfield :: Integer - Word32s - IO () sLbitfield i (Word32s bf) = do modifyIORef bf (shiftL i) main::IO() main = do oper_bf - mkbitfield bitfield sLbitfield 2 oper_bf bf_003.hs:15:48: Couldn't match type `Int' with `Word32' Expected type: Word32 - Word32 Actual type: Int - Word32 In the return type of a call of `shiftL' In the second argument of `modifyIORef', namely `(shiftL i)' In a stmt of a 'do' block: modifyIORef bf (shiftL i) bf_003.hs:15:55: Couldn't match expected type `Word32' with actual type `Integer' In the first argument of `shiftL', namely `i' In the second argument of `modifyIORef', namely `(shiftL i)' In a stmt of a 'do' block: modifyIORef bf (shiftL i) Thanks, --Joerg ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] what is wrong w my IORef Word32 ?
shiftL has the wrong type: Bits a = a - Int - a so it is expecting the value in the IORef to be an Int. Edward Excerpts from Joerg Fritsch's message of Thu Jul 18 10:08:22 -0700 2013: All, what is wrong w the below code? I get an type error related to the operation shiftL import Data.Bits import Data.Word import Data.IORef data Word32s = Word32s { x :: IORef Word32 } bitfield :: Word32 bitfield = 0 mkbitfield :: Word32 - IO Word32s mkbitfield i = do the_bf - newIORef i return (Word32s the_bf) sLbitfield :: Integer - Word32s - IO () sLbitfield i (Word32s bf) = do modifyIORef bf (shiftL i) main::IO() main = do oper_bf - mkbitfield bitfield sLbitfield 2 oper_bf bf_003.hs:15:48: Couldn't match type `Int' with `Word32' Expected type: Word32 - Word32 Actual type: Int - Word32 In the return type of a call of `shiftL' In the second argument of `modifyIORef', namely `(shiftL i)' In a stmt of a 'do' block: modifyIORef bf (shiftL i) bf_003.hs:15:55: Couldn't match expected type `Word32' with actual type `Integer' In the first argument of `shiftL', namely `i' In the second argument of `modifyIORef', namely `(shiftL i)' In a stmt of a 'do' block: modifyIORef bf (shiftL i) Thanks, --Joerg ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] what is wrong w my IORef Word32 ?
Can I easily fix the modifyIORef statement by swapping something ? --Joerg On Jul 18, 2013, at 7:19 PM, Edward Z. Yang ezy...@mit.edu wrote: shiftL has the wrong type: Bits a = a - Int - a so it is expecting the value in the IORef to be an Int. Edward Excerpts from Joerg Fritsch's message of Thu Jul 18 10:08:22 -0700 2013: All, what is wrong w the below code? I get an type error related to the operation shiftL import Data.Bits import Data.Word import Data.IORef data Word32s = Word32s { x :: IORef Word32 } bitfield :: Word32 bitfield = 0 mkbitfield :: Word32 - IO Word32s mkbitfield i = do the_bf - newIORef i return (Word32s the_bf) sLbitfield :: Integer - Word32s - IO () sLbitfield i (Word32s bf) = do modifyIORef bf (shiftL i) main::IO() main = do oper_bf - mkbitfield bitfield sLbitfield 2 oper_bf bf_003.hs:15:48: Couldn't match type `Int' with `Word32' Expected type: Word32 - Word32 Actual type: Int - Word32 In the return type of a call of `shiftL' In the second argument of `modifyIORef', namely `(shiftL i)' In a stmt of a 'do' block: modifyIORef bf (shiftL i) bf_003.hs:15:55: Couldn't match expected type `Word32' with actual type `Integer' In the first argument of `shiftL', namely `i' In the second argument of `modifyIORef', namely `(shiftL i)' In a stmt of a 'do' block: modifyIORef bf (shiftL i) Thanks, --Joerg ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] what is wrong w my IORef Word32 ?
Joerg Fritsch, Thu 2013-07-18 @ 19:22:46+0200: Can I easily fix the modifyIORef statement by swapping something ? --Joerg Replace `shiftL` with `flip shiftL` and change the type signature of `sLbitfield` to take an Int instead of an Integer. signature.asc Description: Digital signature ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] What does it mean to derive equations of restricted from in Haskell?
In John Hughes's The Design of Pretty printing library paper, he says: The implementations which we are trying to derive consist of equations of a restricted form. We will derive implementations by proving their constituent equations from the specification. By itself this is no guarantee that the implemented functions satisfy the specification because we might not have proved enough equation But if we also check that the derived definitions are terminating and exhaustive then this property is guaranteed What does restricted form mean? What is the meaning and significance of definitions are terminating and exhaustive? -- Daryoush Weblog: http://onfp.blogspot.com/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What does it mean to derive equations of restricted from in Haskell?
Daryoush Mehrtash dmehrtash at gmail.com writes: What does restricted form mean? non-restricted: e.g., f (f x y) z = f x (f y z)) restricted: the shape of function declarations in Haskell (where lhs is a pattern) definitions are terminating ... non-termination: an equation like f x y = f y x when you orient it as a rule f x y - f y x, there are infinite derivations and exhaustive non-exhaustive: you have an equation f (x : ys) = ... but you don't have an equation for f [] = ... (all the above is is standard stuff in algebraic specification, equational reasoning, etc.) - J.W. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] What have happened to haskell.org?
On URL http://haskell.org/ I get starting Apache page and 404 on http://haskell.org/hoogle/ URL with starting www - http://www.haskell.org/ seems to be working but http://www.haskell.org/hoogle/ responds with some ELF file. Kind regards, Kirill Zaborsky ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What have happened to haskell.org?
On Mon, Jul 15, 2013 at 07:19:12AM -0700, Kirill Zaborsky wrote: http://www.haskell.org/hoogle/ responds with some ELF file. After running strings on it, it does seem to be (at least part of) the hoogle binary. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What have happened to haskell.org?
The web site is migrating. IRC says: Topic for #haskell: haskell.org in the middle of migration; expect turbulence; use www.haskell.org On Mon, Jul 15, 2013 at 6:19 PM, Kirill Zaborsky qri...@gmail.com wrote: On URL http://haskell.org/ I get starting Apache page and 404 on http://haskell.org/hoogle/ URL with starting www - http://www.haskell.org/ seems to be working but http://www.haskell.org/hoogle/ responds with some ELF file. Kind regards, Kirill Zaborsky ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- Sincerely yours, -- Daniil -- Sincerely yours, -- Daniil ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What symbol / atom/ interned-string package is currently preferred?
http://hackage.haskell.org/package/intern what does this package do? OK, I can read efficient hash consing but what does it mean exactly? and how would I actually use it? - J.W. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What symbol / atom/ interned-string package is currently preferred?
On 05/09/2013 12:56 PM, Johannes Waldmann wrote: http://hackage.haskell.org/package/intern what does this package do? OK, I can read efficient hash consing but what does it mean exactly? and how would I actually use it? I can't tell you what it does, but there is an example - https://github.com/ekmett/intern/blob/master/examples/Term.hs ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What symbol / atom/ interned-string package is currently preferred?
https://github.com/ekmett/intern/blob/master/examples/Term.hs sure I found this but that still does not say much. I known generally what hash consing is (and that's why I think I might want to use this package) but I don't see what is the (implied) contract for this implementation: It looks like I need to write some instances (to make my typ internable) but what properties should they have, and what properties of the functions defined in the package do I get in return? - J.W. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What symbol / atom/ interned-string package is currently preferred?
On Thu, 2013-05-09 at 11:56 +, Johannes Waldmann wrote: http://hackage.haskell.org/package/intern what does this package do? OK, I can read efficient hash consing but what does it mean exactly? and how would I actually use it? Hah. I read the same thing and came to exactly the same level of not-understanding. Thankfully edwardk is learning the value of putting documentation in his libraries! The only trouble is that he is so bloody prolific it might be a while before he gets around to explaining any particular one to the rest of us :) AfC Sydney ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] What symbol / atom/ interned-string package is currently preferred?
Hi cafe, I use symbols all the time when manipulating code. I vacillate between using stringtable-atom, symbol, and simple-atom. Unfortunately: - Stringtable-atom is has a broken build right now (GHC 7.6). (Also I've had some crashes with it in the past.) - simple-atom has dependency upper bounds that restrict it to GHC = 7.0 - symbol has a design flaw, which is that it exposes the constructor for Symbol, which reveals the (nondeterministic) unique Int IDs. I.e. it is not SafeHaskell. I submitted a pull request to relax simple-atom, but perhaps there are other packages people use with which I am not aware? Thanks, -Ryan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What symbol / atom/ interned-string package is currently preferred?
On Tue, May 7, 2013 at 2:58 PM, Ryan Newton rrnew...@gmail.com wrote: Hi cafe, I use symbols all the time when manipulating code. I vacillate between using stringtable-atom, symbol, and simple-atom. Unfortunately: Stringtable-atom is has a broken build right now (GHC 7.6). (Also I've had some crashes with it in the past.) simple-atom has dependency upper bounds that restrict it to GHC = 7.0 symbol has a design flaw, which is that it exposes the constructor for Symbol, which reveals the (nondeterministic) unique Int IDs. I.e. it is not SafeHaskell. I submitted a pull request to relax simple-atom, but perhaps there are other packages people use with which I am not aware? Thanks, -Ryan This package is current and maintained: http://hackage.haskell.org/package/intern Anthony ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] What is the process for GSOC?
How is it decided which Haskell projects get chosen? Do we discuss them here and take a collective view? Thanks, Dominic. PS I should point out I have an interest in the proposal to port charts to use diagrams (http://www.google-melange.com/gsoc/proposal/review/google/gsoc2013/jbracker/1) i.e. I'd really like this as a user. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What is the process for GSOC?
No, if the process is the same this year as the previous one, all potential mentors and haskell.org gsoc admins (I think) get to vote on each submission, giving it a score, and then the best N proposals get chosen. On Wed, May 1, 2013 at 10:34 AM, Dominic Steinitz domi...@steinitz.orgwrote: How is it decided which Haskell projects get chosen? Do we discuss them here and take a collective view? Thanks, Dominic. PS I should point out I have an interest in the proposal to port charts to use diagrams ( http://www.google-melange.com/gsoc/proposal/review/google/gsoc2013/jbracker/1) i.e. I'd really like this as a user. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- Alp Mestanogullari ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] what happened to alexAndPred?
Hi. I have ghc-7.6.3 and alex-3.0.5. When I build https://github.com/jwaldmann/smt-lib it breaks with Language/SMTLIB/Lexer.x:6:5: Not in scope: `alexAndPred'. It was working with alex-2.3.5. I was going t add Can I constrain the alex version in the cabal file (I recall this is difficult for executables since they're not registered with ghc) but it wouldn't help since alex-2.3.5 cannot be built with a recent ghc-7.6 because Module `System.IO.Error' does not export `try'. Also, not with ghc-7.4.2 because of dist/build/alex/alex-tmp/Scan.hs:344:17: Illegal bang-pattern (use -XBangPatterns): And not with = ghc-7.2 because of Linking /tmp/alex-2.3.5-20331/alex-2.3.5/dist/setup/setup ... unrecognized option `--disable-benchmarks' ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] What happened to http://hackage.haskell.org/platform/2010.2.0.0/cabal/haskell-platform-2010.2.0.0.tar.gz?
Is it just me or have some of the old Haskell Platform releases disappeared from haskell.org? The 2010.x links from http://www.haskell.org/platform/prior.html also point to non-existent pages. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What pattern is this (Something.T - IO a) in Sound.ALSA.Sequencer
* Martin Drautzburg martin.drautzb...@web.de [2013-03-04 21:21:30+0100] On Sunday, 3. March 2013 21:11:21 Roman Cheplyaka wrote: Admittedly, programming with callbacks is not very pleasant. So we have an excellent alternative — the continuation monad transformer! This nested code something1 $ \x - do something2 $ \y - do something3 $ \z - do can be equivalently rewritten as this linear code import Control.Monad.Cont flip runContT return $ do x - ContT something1 y - ContT something2 z - ContT something3 lift $ do ... Mind-blowing. Thanks a lot. Before I dig into the continuation monad transformer, one more question (demonstrating my ignorance): The initialization actually starts with main = (do SndSeq.withDefault SndSeq.Block $ \h - do Client.setName (h :: SndSeq.T SndSeq.DuplexMode) Haskell-Melody Port.withSimple h out (Port.caps [Port.capRead, Port.capSubsRead, Port.capWrite]) (Port.types [Port.typeMidiGeneric, Port.typeApplication]) $ \p - do So there are some plain actions like Client.setName and Port.withSimple before it gets to the next do block. How would I write this in ContT style? You can use the lift function to lift actions from the underlying monad to the transformer. In your case it'd be something like flip runContT return $ do h - ContT $ SndSeq.withDefault SndSeq.Block lift $ Client.setName (h :: SndSeq.T SndSeq.DuplexMode) Haskell-Melody p - ContT $ Port.withSimple h out (Port.caps [Port.capRead, Port.capSubsRead, Port.capWrite]) (Port.types [Port.typeMidiGeneric, Port.typeApplication]) ... Roman ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What pattern is this (Something.T - IO a) in Sound.ALSA.Sequencer
On Sunday, 3. March 2013 21:11:21 Roman Cheplyaka wrote: Admittedly, programming with callbacks is not very pleasant. So we have an excellent alternative — the continuation monad transformer! This nested code something1 $ \x - do something2 $ \y - do something3 $ \z - do can be equivalently rewritten as this linear code import Control.Monad.Cont flip runContT return $ do x - ContT something1 y - ContT something2 z - ContT something3 lift $ do ... Mind-blowing. Thanks a lot. Before I dig into the continuation monad transformer, one more question (demonstrating my ignorance): The initialization actually starts with main = (do SndSeq.withDefault SndSeq.Block $ \h - do Client.setName (h :: SndSeq.T SndSeq.DuplexMode) Haskell-Melody Port.withSimple h out (Port.caps [Port.capRead, Port.capSubsRead, Port.capWrite]) (Port.types [Port.typeMidiGeneric, Port.typeApplication]) $ \p - do So there are some plain actions like Client.setName and Port.withSimple before it gets to the next do block. How would I write this in ContT style? -- Martin ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] What pattern is this (Something.T - IO a) in Sound.ALSA.Sequencer
Hello all, this was previously posted on Haskell Beginners, but only partially answered. In Sound.ALSA.Sequencer, there are a number of functions which together set up a midi environement (client, port, queue). They all have a type, where the last argument has a type like: (something.T - IO a) i.e. *Main :t SndSeq.withDefault SndSeq.withDefault :: SndSeq.OpenMode mode = SndSeq.BlockMode - (SndSeq.T mode - IO a) - IO a *Main :t Port.withSimple Port.withSimple :: SndSeq.T mode - String - Port.Cap - Port.Type - (Port.T - IO a) - IO a *Main :t Queue.with Queue.with :: SndSeq.T mode - (Queue.T - IO a) - IO a There is example code, where a full setup is created by a number of nested do blocks. The repeating pattern there is: something1 $ \x - do something2 $ \y - do something3 $ \z - do What is this all about? I particularly would like to understand, when this parttern is needed and what determines the the number of nested do blocks. -- Martin ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What pattern is this (Something.T - IO a) in Sound.ALSA.Sequencer
On Sun, Mar 3, 2013 at 10:28 AM, Martin Drautzburg martin.drautzb...@web.de wrote: Hello all, this was previously posted on Haskell Beginners, but only partially answered. In Sound.ALSA.Sequencer, there are a number of functions which together set up a midi environement (client, port, queue). They all have a type, where the last argument has a type like: (something.T - IO a) These things are in the Kleisli category for IO. In short, an argument with this type is a function which makes an IO action. The function which takes one of these as an action knows how to get a something.T to apply to the function, either because it is an argument to the bigger function, or because the library author knows the monad has an action with the type IO (something.T). This is safer than passing around unconstrained IO actions. For example, consider: outer :: String - (Int - IO ()) - IO () versus outer :: String - IO () - IO () The second type requires that the library user can construct an appropriate IO () action, and the intended dependence on the Int is not statically verified. On the other hand, the first type requires that you pass in an IO () action constructor that explicitly depends on an Int. The only way you can drop the dependence on the Int is if you explicitly ignore it (and you can turn on warnings to catch that kind of thing) i.e. *Main :t SndSeq.withDefault SndSeq.withDefault :: SndSeq.OpenMode mode = SndSeq.BlockMode - (SndSeq.T mode - IO a) - IO a *Main :t Port.withSimple Port.withSimple :: SndSeq.T mode - String - Port.Cap - Port.Type - (Port.T - IO a) - IO a *Main :t Queue.with Queue.with :: SndSeq.T mode - (Queue.T - IO a) - IO a There is example code, where a full setup is created by a number of nested do blocks. The repeating pattern there is: something1 $ \x - do something2 $ \y - do something3 $ \z - do What is this all about? I particularly would like to understand, when this parttern is needed and what determines the the number of nested do blocks. It can be refactored, so it is never needed. On the other hand, it does have nice properties. The x,y, z variables are all in scope when you're in something3's do-block argument. The determining factor in the nesting depth is how many actions which take elements of a Kliesli category for the monad will be sequenced, since each one requires its own lambda-do-block. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What pattern is this (Something.T - IO a) in Sound.ALSA.Sequencer
Hi Martin, These are called continuations or callbacks. In this case, the term callback seems to fit better, since the result of continuation is an IO action. The common use case for callbacks is when you want to release some resources after the IO action completes. Let's look at the definition of withSimple: withSimple :: Seq.T mode - String - Port.Cap - Port.Type - (Port.T - IO a) - IO a withSimple ss s c t = bracket (createSimple ss s c t) (deleteSimple ss) It uses the 'bracket' function (from Control.Exception) to acquire resource, run the given IO action with that resource and release the resource afterwards. An important property of bracket is that it is exception-safe: resources will be released even when the supplied action throws an exception. But ignoring exceptions, withSimple is equivalent to withSimple ss s c t callback = do port - createSimple ss s c t callback port deleteSimple ss port The non-callback version of withSimple is createSimple, which returns the Port itself. But it doesn't release the Port afterwards, because it has no way to know when you've finished working with it. Callbacks can often be found in imperative programming. Almost all GUI libraries and some I/O frameworks (notably, node.js) are based on callbacks. Admittedly, programming with callbacks is not very pleasant. So we have an excellent alternative — the continuation monad transformer! This nested code something1 $ \x - do something2 $ \y - do something3 $ \z - do can be equivalently rewritten as this linear code import Control.Monad.Cont flip runContT return $ do x - ContT something1 y - ContT something2 z - ContT something3 lift $ do ... Notice that we completely change the style of interaction with the library without changing the library itself at all! For a complete example you can look at the ValueGetter monad in the test-framework-golden package. Roman * Martin Drautzburg martin.drautzb...@web.de [2013-03-03 19:28:39+0100] Hello all, this was previously posted on Haskell Beginners, but only partially answered. In Sound.ALSA.Sequencer, there are a number of functions which together set up a midi environement (client, port, queue). They all have a type, where the last argument has a type like: (something.T - IO a) i.e. *Main :t SndSeq.withDefault SndSeq.withDefault :: SndSeq.OpenMode mode = SndSeq.BlockMode - (SndSeq.T mode - IO a) - IO a *Main :t Port.withSimple Port.withSimple :: SndSeq.T mode - String - Port.Cap - Port.Type - (Port.T - IO a) - IO a *Main :t Queue.with Queue.with :: SndSeq.T mode - (Queue.T - IO a) - IO a There is example code, where a full setup is created by a number of nested do blocks. The repeating pattern there is: something1 $ \x - do something2 $ \y - do something3 $ \z - do What is this all about? I particularly would like to understand, when this parttern is needed and what determines the the number of nested do blocks. -- Martin ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] What is a Haskell way to implement flags?
In C usual way is to set some bit in integer variable by shifting or oring,and than check flag integer variable by anding with particular flag value.What is Haskell way? Thanks. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What is a Haskell way to implement flags?
The same as C way. You can import Data.Bits and can use the functions. Prelude import Data.Bits Prelude Data.Bits Data.Bits. Data.Bits... Data.Bits.bitDefault Data.Bits.complementBit Data.Bits.rotate Data.Bits.shift Data.Bits.testBitDefault Data.Bits..|.Data.Bits.bitSize Data.Bits.isSigned Data.Bits.rotateL Data.Bits.shiftL Data.Bits.unsafeShiftL Data.Bits.BitsData.Bits.clearBit Data.Bits.popCount Data.Bits.rotateR Data.Bits.shiftR Data.Bits.unsafeShiftR Data.Bits.bit Data.Bits.complement Data.Bits.popCountDefault Data.Bits.setBit Data.Bits.testBit Data.Bits.xor Prelude Data.Bits (..) 1 2 0 Prelude Data.Bits (..) 2 2 2 I wrote a minimum spanning tree code and rather than maintaining the list of visited nodes, I took a Integer because of arbitrary precision and set the bits accordingly. visited :: Int - Integer - ( Bool , Integer ) visited x vis = ( t == 0 , vis' ) where t = ( B... ) ( B.shiftL ( 1 :: Integer ) x ) vis vis' = ( B..|. ) ( B.shiftL ( 1 :: Integer ) x ) vis Mukesh On Tue, Feb 19, 2013 at 8:41 PM, Branimir Maksimovic bm...@hotmail.comwrote: In C usual way is to set some bit in integer variable by shifting or oring, and than check flag integer variable by anding with particular flag value. What is Haskell way? Thanks. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What is a Haskell way to implement flags?
Quoth Branimir Maksimovic bm...@hotmail.com, In C usual way is to set some bit in integer variable by shifting or oring, and than check flag integer variable by anding with particular flag value. What is Haskell way? Of course you may do the very same thing, if you like. I think if there's only one of these for the entire program, most Haskell programmers would use a Boolean value, as the space you save with a single bit is of too little consequence to bother with bit twiddling in Haskell. The various flags that belong together might be housed in a `record'. Or, in some contexts a list of an algebraic type might be useful - like, if elem FlagDebug flags, or if any (flip elem flags) [FlagDebug, FlagVerbose] Donn ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What is a Haskell way to implement flags?
On Tue, Feb 19, 2013 at 10:11 AM, Branimir Maksimovic bm...@hotmail.comwrote: In C usual way is to set some bit in integer variable by shifting or oring, and than check flag integer variable by anding with particular flag value. What is Haskell way? You can do that, but a somewhat more idiomatic way would be a list (or, slightly less conveniently but more accurately, a Data.Set) of constructors from a flags ADT. -- brandon s allbery kf8nh sine nomine associates allber...@gmail.com ballb...@sinenomine.net unix, openafs, kerberos, infrastructure, xmonadhttp://sinenomine.net ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What is a Haskell way to implement flags?
Brandon Allbery allber...@gmail.com wrote: In C usual way is to set some bit in integer variable by shifting or oring, and than check flag integer variable by anding with particular flag value. What is Haskell way? You can do that, but a somewhat more idiomatic way would be a list (or, slightly less conveniently but more accurately, a Data.Set) of constructors from a flags ADT. The Set way is the one I would prefer. In fact together with lenses you even get the boolean interface and a nice interface in general. Define your option types: data Flag = Debug | Verbose deriving (Ord) data Options = Options { _optFiles :: Set FilePath, _optFlags :: Set Flag } makeLenses ''Options The fun starts when you have a state monad around Options, because then you can use lenses very easily. Let's add a file: optFiles . contains blah.txt .= True Let's set the Verbose flag: optFlags . contains Verbose .= True Let's flip the Verbose flag: optFlags . contains Verbose %= not Are we verbose? verbose - use (optFlags . contains Verbose) Have fun. =) Greets, Ertugrul -- Not to be or to be and (not to be or to be and (not to be or to be and (not to be or to be and ... that is the list monad. signature.asc Description: PGP signature ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] What magic has the new parallel io manager done to improve performance?
I'm curious about the design and trade offs in IO manager, I can point out two changes that should boost performance: 1. Run an IO manager thread on each capability. 2. Use ONESHOT flag to save a system call. I wonder is there anything else? It must be interesting. -- http://yi-programmer.com/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] What magic has the new IO manager done to improve performance ?
I' m curious about the design and trade offs behind the new IO manager. I see two changes from the code: 1. Run IO manager thread on each capability. 2. Use ONESHOT flag to save a system call. Is there other interesting things to know? Is it possible to use epoll's ET mode to save even more system calls? -- http://yi-programmer.com/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What magic has the new parallel io manager done to improve performance?
Sorry for the duplicate post, please ignore this one. On Sunday, February 17, 2013, yi huang wrote: I'm curious about the design and trade offs in IO manager, I can point out two changes that should boost performance: 1. Run an IO manager thread on each capability. 2. Use ONESHOT flag to save a system call. I wonder is there anything else? It must be interesting. -- http://yi-programmer.com/ -- http://yi-programmer.com/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What magic has the new IO manager done to improve performance ?
Hi, On Saturday, February 16, 2013, yi huang wrote: I' m curious about the design and trade offs behind the new IO manager. I see two changes from the code: 1. Run IO manager thread on each capability. 2. Use ONESHOT flag to save a system call. Is there other interesting things to know? Is it possible to use epoll's ET mode to save even more system calls? Andreas and Kazu (CCed) would know more. In addition to the things you mentioned then parallel I/O manager also uses lock striping and is smarter bout when it makes blocking system calls. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] What happened to first-class modules?
I just read this page http://www.haskell.org/haskellwiki/First-class_module. It seems there was not much no ongoing work on this topic... does somebody know what happened to first-class modules? what are the actual research papers about this topic? Thanks -- Ismael ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] what is the purpose of GHC.Exts.lazy?
docs say: The call '(lazy e)' means the same as e, but lazyhttp://hackage.haskell.org/packages/archive/base/latest/doc/html/GHC-Exts.html#v:lazy has a magical strictness property: it is lazy in its first argument, even though its semantics is strict. why do i want to use magic during strictness analysis? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] What is a functional approach to linear algebra routines? I see REPA warns that one must use fusion or risk slow routines.
Apparently using STUarrays in an imperative fashion is fraught with peril (and the performance of molasses). Casey -- -- Regards, KC ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What is the good way to work with list comprehension and UTCTime?
Thank you. Will do. On Mon, Sep 17, 2012 at 7:14 AM, Antoine Latter aslat...@gmail.com wrote: On Sun, Sep 16, 2012 at 5:04 PM, Richard O'Keefe o...@cs.otago.ac.nz wrote: On 15/09/2012, at 5:14 AM, Chris Heller wrote: You might want to have a look at the time-recurrence package: http://hackage.haskell.org/package/time-recurrence For your simple cases you would do something like: Each second: starting (UTCTime ...) $ recur secondly Each minute: starting (UTCTime ...) $ recur minutely Ouch. Look up minutely (my-NEWT-ly) in an English dictionary. Look up secondly while you're there. You can blame RFC 5545 for that one. In section 3.3.10. our frequencies are: freq= SECONDLY / MINUTELY / HOURLY / DAILY / WEEKLY / MONTHLY / YEARLY Antoine ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- 竹密岂妨流水过 山高哪阻野云飞 And for G+, please use magiclouds#gmail.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What is the good way to work with list comprehension and UTCTime?
On 15/09/2012, at 5:14 AM, Chris Heller wrote: You might want to have a look at the time-recurrence package: http://hackage.haskell.org/package/time-recurrence For your simple cases you would do something like: Each second: starting (UTCTime ...) $ recur secondly Each minute: starting (UTCTime ...) $ recur minutely Ouch. Look up minutely (my-NEWT-ly) in an English dictionary. Look up secondly while you're there. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What is the good way to work with list comprehension and UTCTime?
On Sun, Sep 16, 2012 at 5:04 PM, Richard O'Keefe o...@cs.otago.ac.nz wrote: On 15/09/2012, at 5:14 AM, Chris Heller wrote: You might want to have a look at the time-recurrence package: http://hackage.haskell.org/package/time-recurrence For your simple cases you would do something like: Each second: starting (UTCTime ...) $ recur secondly Each minute: starting (UTCTime ...) $ recur minutely Ouch. Look up minutely (my-NEWT-ly) in an English dictionary. Look up secondly while you're there. You can blame RFC 5545 for that one. In section 3.3.10. our frequencies are: freq= SECONDLY / MINUTELY / HOURLY / DAILY / WEEKLY / MONTHLY / YEARLY Antoine ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What is the good way to work with list comprehension and UTCTime?
Antoine has it right, the language is lifted from the RFC. Chris Heller SAS - Advanced Analytics Teragram Research Development phone: 1-617-576-6800 x54237 mobile: 1-617-460-3643 email: hel...@teragram.com On Sep 16, 2012, at 7:14 PM, Antoine Latter aslat...@gmail.com wrote: On Sun, Sep 16, 2012 at 5:04 PM, Richard O'Keefe o...@cs.otago.ac.nz wrote: On 15/09/2012, at 5:14 AM, Chris Heller wrote: You might want to have a look at the time-recurrence package: http://hackage.haskell.org/package/time-recurrence For your simple cases you would do something like: Each second: starting (UTCTime ...) $ recur secondly Each minute: starting (UTCTime ...) $ recur minutely Ouch. Look up minutely (my-NEWT-ly) in an English dictionary. Look up secondly while you're there. You can blame RFC 5545 for that one. In section 3.3.10. our frequencies are: freq= SECONDLY / MINUTELY / HOURLY / DAILY / WEEKLY / MONTHLY / YEARLY Antoine ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What is the good way to work with list comprehension and UTCTime?
On Thu, Sep 13, 2012 at 10:29 PM, Magicloud Magiclouds magicloud.magiclo...@gmail.com wrote: Hi, Simple usage, I could make an instance of Enum to UTCTime, so [utcTime..] could work. But that is so stiff. How if sometimes I want to step by 1 min, sometimes I want to step by 1 sec? So I think some way like [ t | addUTCTime last 60 ] could be nice. But I cannot figure it out Any idea? Try using Prelude.iterate. -Karl ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What is the good way to work with list comprehension and UTCTime?
Consider using the time-lens package. import Data.Time.Lens import Data.Lens.Common List comprehension style: [modL seconds (+ fromIntegral n) t | n - [0..]] [modL minutes (+ n) t | n - [0..]] (you need fromIntegral for seconds, because it is of fractional type in Data.Time). iterate style, as suggested by Karl: iterate (seconds ^+= 1) t iterate (minutes ^+= 1) t On Fri, Sep 14, 2012 at 7:29 AM, Magicloud Magiclouds magicloud.magiclo...@gmail.com wrote: Hi, Simple usage, I could make an instance of Enum to UTCTime, so [utcTime..] could work. But that is so stiff. How if sometimes I want to step by 1 min, sometimes I want to step by 1 sec? So I think some way like [ t | addUTCTime last 60 ] could be nice. But I cannot figure it out Any idea? -- 竹密岂妨流水过 山高哪阻野云飞 And for G+, please use magiclouds#gmail.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
Re: [Haskell-cafe] What is the good way to work with list comprehension and UTCTime?
This is nice. Thanks to all. On Fri, Sep 14, 2012 at 4:03 PM, Roman Cheplyaka r...@ro-che.info wrote: Consider using the time-lens package. import Data.Time.Lens import Data.Lens.Common List comprehension style: [modL seconds (+ fromIntegral n) t | n - [0..]] [modL minutes (+ n) t | n - [0..]] (you need fromIntegral for seconds, because it is of fractional type in Data.Time). iterate style, as suggested by Karl: iterate (seconds ^+= 1) t iterate (minutes ^+= 1) t On Fri, Sep 14, 2012 at 7:29 AM, Magicloud Magiclouds magicloud.magiclo...@gmail.com wrote: Hi, Simple usage, I could make an instance of Enum to UTCTime, so [utcTime..] could work. But that is so stiff. How if sometimes I want to step by 1 min, sometimes I want to step by 1 sec? So I think some way like [ t | addUTCTime last 60 ] could be nice. But I cannot figure it out Any idea? -- 竹密岂妨流水过 山高哪阻野云飞 And for G+, please use magiclouds#gmail.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- 竹密岂妨流水过 山高哪阻野云飞 And for G+, please use magiclouds#gmail.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] What is the good way to work with list comprehension and UTCTime?
Hi, Simple usage, I could make an instance of Enum to UTCTime, so [utcTime..] could work. But that is so stiff. How if sometimes I want to step by 1 min, sometimes I want to step by 1 sec? So I think some way like [ t | addUTCTime last 60 ] could be nice. But I cannot figure it out Any idea? -- 竹密岂妨流水过 山高哪阻野云飞 And for G+, please use magiclouds#gmail.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What Haskell Records Need
Evan Laforge wrote: I consider that a strength of the lens approach. If I say 'set (a.b.c.d) 42 record', 'a', 'b' etc. don't have to be record fields, I can swap them out for other lenses later on. I can also easily precompose, e.g. 'setThis = a . b; setThat = b . c' and encourage people to use the composed ones (or require via export lists). This corresponds to asking in that it introduces a point of abstraction where I can change all access / modification in one place, or a module can retain control by only exporting the composed version. The same is true with SEC functions: personsSalary' :: (Salary - Salary) - Person - Person personsSalary' = job' . salary' Here I've created a new updater that is composed of 2 that are generated for me (from the examples given in the original email). I can export whichever of these functions I like, generated or otherwise, and keep as much abstraction as I like! The nice part about the SEC functions is that they compose as regular functions. Lenses are super powerful in that they form a category. Unfortunately using categories other than functions feels a tad unwieldy because you have to hide something from prelude and then import Category. (A bit like exceptions, currently). If you like the look of set with lenses, you could define a helper function to use with SEC updaters. set :: ((b - a) - c) - a - c set sec = sec . const --and then use it like so: setPersonsSalary :: Salary - Person - Person setPersonsSalary salary = set personsSalary' salary With it you can use an updater as a setter. I'd like to reiterate one of finer points of the original proposal. The compiler could disallow using old-style update syntax for fields whose SEC update function is not in scope, giving us fine-grained control over access and update. On the other hand we currently have to create new functions to achieve this (exporting the getter means exporting the ability to update [using update syntax] as well, currently). And now back to lenses: it is really convenient how lenses let you compose the getter and setter together. I don't recall too many cases where having the getter and setter and modifier all in one place was terribly useful. Could anyone give me an example? But again, where that is useful, a lens can be created from a getter and a SEC updater. Thoughts? --Jonathan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What Haskell Records Need
On Fri, Aug 3, 2012 at 10:11 AM, Jonathan Geddes geddes.jonat...@gmail.comwrote: The nice part about the SEC functions is that they compose as regular functions. Lenses are super powerful in that they form a category. Unfortunately using categories other than functions feels a tad unwieldy because you have to hide something from prelude and then import Category. (A bit like exceptions, currently). FWIW this is also true for van Laarhoven lenses[1] type FTLens a b = forall f. Functor f = (b - f b) - (a - f a) newtype Const a b = Const { unConst :: a } deriving Functor get :: FTLens a b - a - b get ft = unConst . ft Const {- ft :: forall f. (b - f b) - (a - f a) Const :: forall x. b - Const b x ft Const :: a - Const b a -} newtype Id a = Id { unId :: a } deriving Functor set :: FTLens a b - b - a - a set ft b = unId . ft (\_ - Id b) modify :: FTLens a b - (b - b) - a - a modify ft k = unId . ft (Id . k) -- example fstLens :: FTLens (a,b) a fstLens aToFa (a,b) = (,b) $ aToFa a -- and you get compose :: FTLens b c - FTLens a b - FTLens a c compose = (.) identity :: FTLens a a identity = id If you like the look of set with lenses, you could define a helper function to use with SEC updaters. set :: ((b - a) - c) - a - c set sec = sec . const --and then use it like so: setPersonsSalary :: Salary - Person - Person setPersonsSalary salary = set personsSalary' salary With it you can use an updater as a setter. I'd like to reiterate one of finer points of the original proposal. The compiler could disallow using old-style update syntax for fields whose SEC update function is not in scope, giving us fine-grained control over access and update. On the other hand we currently have to create new functions to achieve this (exporting the getter means exporting the ability to update [using update syntax] as well, currently). And now back to lenses: it is really convenient how lenses let you compose the getter and setter together. I don't recall too many cases where having the getter and setter and modifier all in one place was terribly useful. Could anyone give me an example? But again, where that is useful, a lens can be created from a getter and a SEC updater. Thoughts? --Jonathan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What Haskell Records Need
Oops, forgot my references [1] Original post: http://www.twanvl.nl/blog/haskell/cps-functional-references [2] polymorphic update support: http://r6.ca/blog/20120623T104901Z.html [3] another post about these: http://comonad.com/reader/2012/mirrored-lenses/ On Fri, Aug 3, 2012 at 1:53 PM, Ryan Ingram ryani.s...@gmail.com wrote: On Fri, Aug 3, 2012 at 10:11 AM, Jonathan Geddes geddes.jonat...@gmail.com wrote: The nice part about the SEC functions is that they compose as regular functions. Lenses are super powerful in that they form a category. Unfortunately using categories other than functions feels a tad unwieldy because you have to hide something from prelude and then import Category. (A bit like exceptions, currently). FWIW this is also true for van Laarhoven lenses[1] type FTLens a b = forall f. Functor f = (b - f b) - (a - f a) newtype Const a b = Const { unConst :: a } deriving Functor get :: FTLens a b - a - b get ft = unConst . ft Const {- ft :: forall f. (b - f b) - (a - f a) Const :: forall x. b - Const b x ft Const :: a - Const b a -} newtype Id a = Id { unId :: a } deriving Functor set :: FTLens a b - b - a - a set ft b = unId . ft (\_ - Id b) modify :: FTLens a b - (b - b) - a - a modify ft k = unId . ft (Id . k) -- example fstLens :: FTLens (a,b) a fstLens aToFa (a,b) = (,b) $ aToFa a -- and you get compose :: FTLens b c - FTLens a b - FTLens a c compose = (.) identity :: FTLens a a identity = id If you like the look of set with lenses, you could define a helper function to use with SEC updaters. set :: ((b - a) - c) - a - c set sec = sec . const --and then use it like so: setPersonsSalary :: Salary - Person - Person setPersonsSalary salary = set personsSalary' salary With it you can use an updater as a setter. I'd like to reiterate one of finer points of the original proposal. The compiler could disallow using old-style update syntax for fields whose SEC update function is not in scope, giving us fine-grained control over access and update. On the other hand we currently have to create new functions to achieve this (exporting the getter means exporting the ability to update [using update syntax] as well, currently). And now back to lenses: it is really convenient how lenses let you compose the getter and setter together. I don't recall too many cases where having the getter and setter and modifier all in one place was terribly useful. Could anyone give me an example? But again, where that is useful, a lens can be created from a getter and a SEC updater. Thoughts? --Jonathan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What Haskell Records Need
On 2/08/2012, at 5:34 PM, Jonathan Geddes wrote: Ouch! And that's not even very deeply nested. Imagine 4 or 5 levels deep. It really makes Haskell feel clunky next to `a.b.c.d = val` that you see in other languages. I was taught that this kind of thing violates the Law of Demeter and that an object should not be mutating the parts of an acquaintance's parts, but should ask the acquaintance to do so. I'd say that a.b.c.d = val is at the very least a sign that some encapsulation did not happen. Semantic editor combinators are ingenious, but they make me feel somewhat uneasy, in that they really are in some sense about the *syntax* (or maybe the concrete representation) of things rather than their *semantics* (or maybe I mean the abstract value). ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What Haskell Records Need
Isn't this exactly the problem solved by all the lens packages? Current popular ones are fclabels [0] and data-lens [1]. [0] http://hackage.haskell.org/package/fclabels [1] http://hackage.haskell.org/package/data-lens On Thu, Aug 2, 2012 at 7:34 AM, Jonathan Geddes geddes.jonat...@gmail.com wrote: Greetings, tl;dr - What Haskell Records need are semantic editor combinators for free. I know this is yet another Record proposal among many, but none of them out there strike me as being exactly what I want in Haskell. Take the following types from a contrived example. type Salary = Integer data Job = Job { title :: String , salary :: Salary } data Person = Person { name :: String , job :: Job } Since I've used record syntax, I get getter/accessor functions (title, salary, name, job) for free. Now suppose I want to create an aggregate getter function: return the salary of a given person. Piece of cake, it's just function composition getSalary :: Person - Salary getSalary = salary . job Done! Now suppose I want to write a setter/mutator function for the same nested field setSalaryMessy :: Salary - Person - Person setSalaryMessy newSalary person = person { job = (job person) { salary = newSalary } } Ouch! And that's not even very deeply nested. Imagine 4 or 5 levels deep. It really makes Haskell feel clunky next to `a.b.c.d = val` that you see in other languages. Of course immutability means that the semantics of Haskell are quite different (we're creating new values here, not updating old ones) but it's still common to model change using these kinds of updates. What if along with the free getters that the compiler generates when we use record syntax, we also got semantic editor combinator (SEC) functions[0] that could be used as follows? setSalary newSalary = job' $ salary' (const newSalary) giveRaise amount = job' $ salary' (+amount) givePercentRaise percent = job' $ salary' (*(1+percent)) For each field x, the compiler generates a function x' (the tic is mnemonic for change). These little functions aren't hard to write, but they're classic boilerplate. job' :: (Job - Job) - Person - Person job' f person = person {job = f $ job person} salary' :: (Salary - Salary) - Job - Job salary' f job = job { salary = f $ salary job} These type of utility functions are a dream when working with any reference type or State Monad. modify $ givePercentRaise 0.25 The compiler could also generate polymorphic SEC functions for polymorphic fields. Further, the compiler could disallow using old-style update syntax for fields whose SEC update function is not in scope, giving us fine-grained control over access and update. On the other hand we currently have to create new functions to achieve this (exporting the getter means exporting the ability to update as well, currently). Of course this doesn't address the namespacing issues with records, but it is likely nicely orthogonal to other proposals which do. Also note that there's a package on hackage [1] that will generate SEC functions using TH. It's nice, but I prefer the style of field names used above for updaters (field' vs editField). Let me know what you think. I'll write up an official proposal if there's a bit of general interest around this. Thanks for reading, --Jonathan [0] - http://conal.net/blog/posts/semantic-editor-combinators [1] - http://hackage.haskell.org/packages/archive/sec/0.0.1/doc/html/Data-SemanticEditors.html ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What Haskell Records Need
On 2 Aug 2012, at 09:25, Erik Hesselink wrote: Isn't this exactly the problem solved by all the lens packages? Current popular ones are fclabels [0] and data-lens [1]. [0] http://hackage.haskell.org/package/fclabels [1] http://hackage.haskell.org/package/data-lens Not sure what all of these do, but I have a simple solution I use in my work: Take the following types from a contrived example. type Salary = Integer data Job = Job { title :: String , salary :: Salary } Rather than setTitle :: String - Job - Job we lift the first argument and define setfTitle :: (String - String) - Job - Job setfTitle f jobrec = jobrec{ title = f $ title jobrec } then setTitle = setfTitle . const This is all just boilerplate, so we continue setfSalary :: (Salary - Salary) - Job - Job setfSalary f jobrec = jobrec{ salary = f $ salary jobrec } data Person = Person { name :: String , job :: Job } setfName :: (String - String) - Person - Person setfName f prec = prec{ name = f $ name prec } setfJob :: (Job - Job) - Person - Person setfJob f prec = prec{ job = f $ job prec } Now we can use function composition to do two levels setfTitleInPerson :: (String - String) - Person - Person setfTitleInPerson = setfJob . setfTitle setTitleInPerson :: String - Person - Person setTitleInPerson = setfTitleInPerson . const Simple function composition works to put these together... I was frustrated by this problem a while back, and decided to approach it formally (I write literate Haskell/LateX documents), and went to work, doing the math with the intention of writing a suitable combinator, until I discovered I didn't need one lifting from X - R - R to (X - X) - R - R gave me all I needed... Since I've used record syntax, I get getter/accessor functions (title, salary, name, job) for free. Now suppose I want to create an aggregate getter function: return the salary of a given person. Piece of cake, it's just function composition getSalary :: Person - Salary getSalary = salary . job Done! Now suppose I want to write a setter/mutator function for the same nested field setSalaryMessy :: Salary - Person - Person setSalaryMessy newSalary person = person { job = (job person) { salary = newSalary } } Ouch! And that's not even very deeply nested. Imagine 4 or 5 levels deep. It really makes Haskell feel clunky next to `a.b.c.d = val` that you see in other languages. Of course immutability means that the semantics of Haskell are quite different (we're creating new values here, not updating old ones) but it's still common to model change using these kinds of updates. What if along with the free getters that the compiler generates when we use record syntax, we also got semantic editor combinator (SEC) functions[0] that could be used as follows? setSalary newSalary = job' $ salary' (const newSalary) giveRaise amount = job' $ salary' (+amount) givePercentRaise percent = job' $ salary' (*(1+percent)) For each field x, the compiler generates a function x' (the tic is mnemonic for change). These little functions aren't hard to write, but they're classic boilerplate. job' :: (Job - Job) - Person - Person job' f person = person {job = f $ job person} salary' :: (Salary - Salary) - Job - Job salary' f job = job { salary = f $ salary job} These type of utility functions are a dream when working with any reference type or State Monad. modify $ givePercentRaise 0.25 The compiler could also generate polymorphic SEC functions for polymorphic fields. Further, the compiler could disallow using old-style update syntax for fields whose SEC update function is not in scope, giving us fine-grained control over access and update. On the other hand we currently have to create new functions to achieve this (exporting the getter means exporting the ability to update as well, currently). Of course this doesn't address the namespacing issues with records, but it is likely nicely orthogonal to other proposals which do. Also note that there's a package on hackage [1] that will generate SEC functions using TH. It's nice, but I prefer the style of field names used above for updaters (field' vs editField). Let me know what you think. I'll write up an official proposal if there's a bit of general interest around this. Thanks for reading, --Jonathan [0] - http://conal.net/blog/posts/semantic-editor-combinators [1] - http://hackage.haskell.org/packages/archive/sec/0.0.1/doc/html/Data-SemanticEditors.html ___ 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 Andrew Butterfield
Re: [Haskell-cafe] What Haskell Records Need
Ah yes - the joy of Haskell It so easy to roll your own, rather than search to find someone else's (better/more elegant) solution... :-) On 2 Aug 2012, at 11:41, Erik Hesselink wrote: On Thu, Aug 2, 2012 at 12:30 PM, Andrew Butterfield andrew.butterfi...@scss.tcd.ie wrote: On 2 Aug 2012, at 09:25, Erik Hesselink wrote: Isn't this exactly the problem solved by all the lens packages? Current popular ones are fclabels [0] and data-lens [1]. [0] http://hackage.haskell.org/package/fclabels [1] http://hackage.haskell.org/package/data-lens Not sure what all of these do, but I have a simple solution I use in my work: They do exactly that. They create 'lenses' which are getters/setters/modifiers combined, and allow you to compose these to get/set/modify deep inside nested data types. Look at the examples in the fclabels documentation [2] for more details. [2] http://hackage.haskell.org/packages/archive/fclabels/1.1.4/doc/html/Data-Label.html Andrew Butterfield Tel: +353-1-896-2517 Fax: +353-1-677-2204 Lero@TCD, Head of Foundations Methods Research Group Director of Teaching and Learning - Undergraduate, School of Computer Science and Statistics, Room G.39, O'Reilly Institute, Trinity College, University of Dublin http://www.scss.tcd.ie/Andrew.Butterfield/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What Haskell Records Need
On Thu, Aug 2, 2012 at 12:30 PM, Andrew Butterfield andrew.butterfi...@scss.tcd.ie wrote: On 2 Aug 2012, at 09:25, Erik Hesselink wrote: Isn't this exactly the problem solved by all the lens packages? Current popular ones are fclabels [0] and data-lens [1]. [0] http://hackage.haskell.org/package/fclabels [1] http://hackage.haskell.org/package/data-lens Not sure what all of these do, but I have a simple solution I use in my work: They do exactly that. They create 'lenses' which are getters/setters/modifiers combined, and allow you to compose these to get/set/modify deep inside nested data types. Look at the examples in the fclabels documentation [2] for more details. [2] http://hackage.haskell.org/packages/archive/fclabels/1.1.4/doc/html/Data-Label.html ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What Haskell Records Need
Richard O'Keefe Said: Ouch! And that's not even very deeply nested. Imagine 4 or 5 levels deep. It really makes Haskell feel clunky next to `a.b.c.d = val` that you see in other languages. I was taught that this kind of thing violates the Law of Demeter and that an object should not be mutating the parts of an acquaintance's parts, but should ask the acquaintance to do so. I'd say that a.b.c.d = val is at the very least a sign that some encapsulation did not happen. Absolutely! But in Haskell how do you do the asking? I guess that's what I'm proposing is a built in way of doing just that! I'm shooting for as-easy-as the built in getters. Erik Hesselink said: Isn't this exactly the problem solved by all the lens packages? Yes it is. I think the existence of these packages along with all the proposals to change records is an indication that something is missing from the language as a whole. What I'm proposing is that the language give you something that is lightweight and easy to use to address this issue. You can still use lenses on top of all of this. makeLens myField myField' If I remember correctly, one of the problems with lenses is that they cannot support polymorphic updates (updates which change a type variable of the data). SEC functions, on the other hand support polymorphic updates. --Jonathan On Thu, Aug 2, 2012 at 4:48 AM, Andrew Butterfield andrew.butterfi...@scss.tcd.ie wrote: Ah yes - the joy of Haskell It so easy to roll your own, rather than search to find someone else's (better/more elegant) solution... :-) On 2 Aug 2012, at 11:41, Erik Hesselink wrote: On Thu, Aug 2, 2012 at 12:30 PM, Andrew Butterfield andrew.butterfi...@scss.tcd.ie wrote: On 2 Aug 2012, at 09:25, Erik Hesselink wrote: Isn't this exactly the problem solved by all the lens packages? Current popular ones are fclabels [0] and data-lens [1]. [0] http://hackage.haskell.org/package/fclabels [1] http://hackage.haskell.org/package/data-lens Not sure what all of these do, but I have a simple solution I use in my work: They do exactly that. They create 'lenses' which are getters/setters/modifiers combined, and allow you to compose these to get/set/modify deep inside nested data types. Look at the examples in the fclabels documentation [2] for more details. [2] http://hackage.haskell.org/packages/archive/fclabels/1.1.4/doc/html/Data-Label.html Andrew Butterfield Tel: +353-1-896-2517 Fax: +353-1-677-2204 Lero@TCD, Head of Foundations Methods Research Group Director of Teaching and Learning - Undergraduate, School of Computer Science and Statistics, Room G.39, O'Reilly Institute, Trinity College, University of Dublin http://www.scss.tcd.ie/Andrew.Butterfield/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What Haskell Records Need
I'm new to Haskell, but I do like your idea. I prefer this as a built-in feature because it will create a standard way of doing this, making the question wich package should I use to get mutatos? lens-foo, lens-bar, monad-lens, lens-lens-foo-bar, ...? simply go away. So, yes, I up-vote your idea to write an official proposal. Thiago. 2012/8/2 Jonathan Geddes geddes.jonat...@gmail.com: Richard O'Keefe Said: Ouch! And that's not even very deeply nested. Imagine 4 or 5 levels deep. It really makes Haskell feel clunky next to `a.b.c.d = val` that you see in other languages. I was taught that this kind of thing violates the Law of Demeter and that an object should not be mutating the parts of an acquaintance's parts, but should ask the acquaintance to do so. I'd say that a.b.c.d = val is at the very least a sign that some encapsulation did not happen. Absolutely! But in Haskell how do you do the asking? I guess that's what I'm proposing is a built in way of doing just that! I'm shooting for as-easy-as the built in getters. Erik Hesselink said: Isn't this exactly the problem solved by all the lens packages? Yes it is. I think the existence of these packages along with all the proposals to change records is an indication that something is missing from the language as a whole. What I'm proposing is that the language give you something that is lightweight and easy to use to address this issue. You can still use lenses on top of all of this. makeLens myField myField' If I remember correctly, one of the problems with lenses is that they cannot support polymorphic updates (updates which change a type variable of the data). SEC functions, on the other hand support polymorphic updates. --Jonathan On Thu, Aug 2, 2012 at 4:48 AM, Andrew Butterfield andrew.butterfi...@scss.tcd.ie wrote: Ah yes - the joy of Haskell It so easy to roll your own, rather than search to find someone else's (better/more elegant) solution... :-) On 2 Aug 2012, at 11:41, Erik Hesselink wrote: On Thu, Aug 2, 2012 at 12:30 PM, Andrew Butterfield andrew.butterfi...@scss.tcd.ie wrote: On 2 Aug 2012, at 09:25, Erik Hesselink wrote: Isn't this exactly the problem solved by all the lens packages? Current popular ones are fclabels [0] and data-lens [1]. [0] http://hackage.haskell.org/package/fclabels [1] http://hackage.haskell.org/package/data-lens Not sure what all of these do, but I have a simple solution I use in my work: They do exactly that. They create 'lenses' which are getters/setters/modifiers combined, and allow you to compose these to get/set/modify deep inside nested data types. Look at the examples in the fclabels documentation [2] for more details. [2] http://hackage.haskell.org/packages/archive/fclabels/1.1.4/doc/html/Data-Label.html Andrew Butterfield Tel: +353-1-896-2517 Fax: +353-1-677-2204 Lero@TCD, Head of Foundations Methods Research Group Director of Teaching and Learning - Undergraduate, School of Computer Science and Statistics, Room G.39, O'Reilly Institute, Trinity College, University of Dublin http://www.scss.tcd.ie/Andrew.Butterfield/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What Haskell Records Need
On Thu, Aug 2, 2012 at 9:00 AM, Jonathan Geddes geddes.jonat...@gmail.com wrote: Richard O'Keefe Said: Ouch! And that's not even very deeply nested. Imagine 4 or 5 levels deep. It really makes Haskell feel clunky next to `a.b.c.d = val` that you see in other languages. I was taught that this kind of thing violates the Law of Demeter and that an object should not be mutating the parts of an acquaintance's parts, but should ask the acquaintance to do so. I'd say that a.b.c.d = val is at the very least a sign that some encapsulation did not happen. Absolutely! But in Haskell how do you do the asking? I guess that's what I'm proposing is a built in way of doing just that! I'm shooting for as-easy-as the built in getters. I consider that a strength of the lens approach. If I say 'set (a.b.c.d) 42 record', 'a', 'b' etc. don't have to be record fields, I can swap them out for other lenses later on. I can also easily precompose, e.g. 'setThis = a . b; setThat = b . c' and encourage people to use the composed ones (or require via export lists). This corresponds to asking in that it introduces a point of abstraction where I can change all access / modification in one place, or a module can retain control by only exporting the composed version. Erik Hesselink said: Isn't this exactly the problem solved by all the lens packages? Yes it is. I think the existence of these packages along with all the proposals to change records is an indication that something is missing from the language as a whole. What I'm proposing is that the language give you something that is lightweight and easy to use to address this issue. You can still use lenses on top of all of this. I put up a record suggestion a while back that was in two parts, one was a default lens implementation and the ability to write 'deriving (Lens)' on a record to create the lenses. The other was some magic syntax to make it easier to type in the lens names. Actually it was mostly magic syntax, since 'deriving (Lens)' pretty much speaks for itself, though you'd need to include a default lens implementation in the stdlib. I think that's a good idea anyway, but on the other hand people are still innovating in lens land. But back on the first hand again, threat of inclusion in the stdlib might force a much-needed consolidation and polishing in the lens world (pun honestly not intended). Automatically creating something (semantic editors) which isn't lenses but makes it easier to write lenses is an interesting compromise, though it is really convenient how lenses let you compose the getter and setter together. But I've found that even one line of boilerplate for each record field is already enough to discourage me from writing one for each record field since it only pays off if there's a nested update. If I remember correctly, one of the problems with lenses is that they cannot support polymorphic updates (updates which change a type variable of the data). SEC functions, on the other hand support polymorphic updates. This has been solved, yes? I haven't gotten time to investigate fully, but: http://hackage.haskell.org/package/lens-family I should look into it and update the lensy-record proposal if they're appropriate. Though it would be nice to see feedback on it, point out a fatal flaw, or at least someone could mention they read it, so I can know whether or not it's worth spending the time: http://hackage.haskell.org/trac/ghc/wiki/Records/SyntaxDirectedNameResolution ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] What Haskell Records Need
Greetings, tl;dr - What Haskell Records need are semantic editor combinators for free. I know this is yet another Record proposal among many, but none of them out there strike me as being exactly what I want in Haskell. Take the following types from a contrived example. type Salary = Integer data Job = Job { title :: String , salary :: Salary } data Person = Person { name :: String , job :: Job } Since I've used record syntax, I get getter/accessor functions (title, salary, name, job) for free. Now suppose I want to create an aggregate getter function: return the salary of a given person. Piece of cake, it's just function composition getSalary :: Person - Salary getSalary = salary . job Done! Now suppose I want to write a setter/mutator function for the same nested field setSalaryMessy :: Salary - Person - Person setSalaryMessy newSalary person = person { job = (job person) { salary = newSalary } } Ouch! And that's not even very deeply nested. Imagine 4 or 5 levels deep. It really makes Haskell feel clunky next to `a.b.c.d = val` that you see in other languages. Of course immutability means that the semantics of Haskell are quite different (we're creating new values here, not updating old ones) but it's still common to model change using these kinds of updates. What if along with the free getters that the compiler generates when we use record syntax, we also got semantic editor combinator (SEC) functions[0] that could be used as follows? setSalary newSalary = job' $ salary' (const newSalary) giveRaise amount = job' $ salary' (+amount) givePercentRaise percent = job' $ salary' (*(1+percent)) For each field x, the compiler generates a function x' (the tic is mnemonic for change). These little functions aren't hard to write, but they're classic boilerplate. job' :: (Job - Job) - Person - Person job' f person = person {job = f $ job person} salary' :: (Salary - Salary) - Job - Job salary' f job = job { salary = f $ salary job} These type of utility functions are a dream when working with any reference type or State Monad. modify $ givePercentRaise 0.25 The compiler could also generate polymorphic SEC functions for polymorphic fields. Further, the compiler could disallow using old-style update syntax for fields whose SEC update function is not in scope, giving us fine-grained control over access and update. On the other hand we currently have to create new functions to achieve this (exporting the getter means exporting the ability to update as well, currently). Of course this doesn't address the namespacing issues with records, but it is likely nicely orthogonal to other proposals which do. Also note that there's a package on hackage [1] that will generate SEC functions using TH. It's nice, but I prefer the style of field names used above for updaters (field' vs editField). Let me know what you think. I'll write up an official proposal if there's a bit of general interest around this. Thanks for reading, --Jonathan [0] - http://conal.net/blog/posts/semantic-editor-combinators [1] - http://hackage.haskell.org/packages/archive/sec/0.0.1/doc/html/Data-SemanticEditors.html ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What does unpacking an MVar really mean?
Leon Smith wrote: I am familiar with the source of Control.Concurrent.MVar, and I do see {-# UNPACK #-}'ed MVars around, for example in GHC's IO manager. What I should have asked is, what does an MVar# look like? This cannot be inferred from Haskell source; though I suppose I could have tried to read the Runtime source. So let's have a brief look at the source. MVar# is an RTS specific heap object which contains three pointers: (from ghc/includes/rts/storage/Closures.h) typedef struct { StgHeaderheader; struct StgMVarTSOQueue_ *head; struct StgMVarTSOQueue_ *tail; StgClosure* value; } StgMVar; The 'value' pointer refers to the actual value held by the mutable variable, if any. The 'head' and 'tail' pointers are used for managing a linked list of threads blocked on the mutable variable. An MVar (if evaluated) contains just a pointer the MVar# object. To access the value of an MVar, one starts with a pointer to the MVar heap object. Then, 1. Make sure that the MVar is evaluated, using standard lazy evaluation (follow indirections, enter thunks, ...). In the best case that's a check of a tag bit in the pointer. 2. Read the pointer to the MVar# in the MVar. 3. access the 'value' field of the StgMVar record, which results in another pointer to a heap object representing the actual data held by the MVar. (In reality the code has to check whether the MVar is full or not, and block if necessary. This is quite involved; see stg_takeMVarzh in ghc/rts/PrimOps.cmm) That's two dereferences and some bookkeeping work. In loops, the compiler will often unpack the MVar, so that you can expect the first two steps to be performed just once. Unpacking an MVar into a bigger record means that the pointer to the MVar# will be stored in the record directly, rather than a pointer to an MVar object that holds a pointer to the MVar#. Note that MVar# itself cannot be unpacked -- the StgMVar record will always be a separate heap object. I was asking the dual question: if the MVar# exists in some data structure, can that data structure still be garbage collected when there is a reference to the MVar#, but not the data structure it is contained within. Yes, because the data structure only contains a pointer to an MVar# (StgMVar record) that will live on. Best regards, Bertram ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What does unpacking an MVar really mean?
On Tue, Jul 31, 2012 at 7:37 AM, Bertram Felgenhauer bertram.felgenha...@googlemail.com wrote: Note that MVar# itself cannot be unpacked -- the StgMVar record will always be a separate heap object. One could imagine a couple of techniques to unpack the MVar# itself, and was curious if GHC might employ one of them. So, really, unpacking the MVar does not eliminate a layer of indirection, it just eliminates the need to check a pointer tag (and possibly execute a thunk or follow some redirects if you don't have a pointer to an MVar#). I think this is what I was ultimately after. Best, Leon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] What does unpacking an MVar really mean?
I admit I don't know exactly how MVars are implemented, but given that they can be aliased and have indefinite extent, I would think that they look something vaguely like a cdatatype ** var, basically a pointer to an MVar (which is itself a pointer, modulo some other things such as a thread queue.) And, I would think that unpacking such an structure would basically be eliminating one layer of indirection, so it would then look vague like a cdatatype * var.But again, given aliasing and indefinite extent, this would seem to be a difficult thing to do. Actually this isn't too difficult if an MVar only exists in a single unpacked structure: other references to the MVar can simply be pointers into the structure. But the case where an MVar is unpacked into two different structures suggests that, at least in some cases, an unpacked MVar is still a cdatatype ** var; So, is my understanding more or less correct? Does anybody have a good, succinct explanation of how MVars are implemented, and how they are unpacked? One final question, assuming that unpacking an MVar really does eliminate a layer of indirection, and that other references to that MVar are simply pointers into a larger structure, what happens to that larger structure when there are no more references to it (but still some references to the MVar?)Given the complications that must arise out of a doubly unpacked MVar, I'm going to guess that the larger structure does get garbage collected in this case, and that the MVar becomes dislodged from this structure. Would that MVar then be placed directly inside another unpacked reference, if one is available? Best, Leon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What does unpacking an MVar really mean?
I'm not sure I totally understand your question about 'unpacking' an MVar, but I'm going to assume you mean data structures that use the {-# UNPACK #-} pragma, like in Control.Concurrent.Future [1] and Control.Concurrent.NamedLock [2]. Here is how MVar is defined in GHC [3]: data MVar a = MVar (MVar# RealWorld a) A MVar# s a is an unboxed pointer to a structure understood by the GHC runtime. So yes, you can imagine a MVar as a pointer-to-pointer. The structure it points at likely has another pointer to the embedded boxed a, so it may even be pointer-to-pointer-to-pointer. The MVar data structure exists to allow laziness; for example let x = unsafePerformIO (newMVar ()) in () is likely to not allocate an MVar#, just a thunk that would create an MVar if it was evaluated. Unboxed objects (represented by convetion with # in GHC), on the other hand, are strict, so if you have an MVar# RealWorld (), you know it points to a valid MVar#. From [2] we have data NLItem = NLItem {-# UNPACK #-} !Int {-# UNPACK #-} !(MVar ()) All the {-# UNPACK #-} pragma does is embed the contents of a strict single-constructor data declaration *directly* into the structure containing it; it's like you declared NLItem as such: data NLItem = NLItem Word# (MVar# RealWorld ()) except that if you call functions that want an Int or MVar thunk, the compiler will automatically re-box them in a new I#/MVar constructor. Many copies of pointers to the same MVar# may exist; they are all 'identical' MVars; equality is defined as such: instance Eq (MVar a) where (MVar mvar1#) == (MVar mvar2#) = sameMVar# mvar1# mvar2# where sameMVar# is a primitive that is probably just raw pointer equality. Because of this, boxed MVars can be garbage collected without necessarily garbage-collecting the MVar# it holds, if a live reference to that MVar# still exists elsewhere. -- ryan [1] http://hackage.haskell.org/packages/archive/future/2.0.0/doc/html/src/Control-Concurrent-Future.html [2] http://hackage.haskell.org/packages/archive/named-lock/0.1/doc/html/src/Control-Concurrent-NamedLock.html [3] http://www.haskell.org/ghc/docs/7.4.1/html/libraries/base/src/GHC-MVar.html#MVar On Mon, Jul 30, 2012 at 9:25 PM, Leon Smith leon.p.sm...@gmail.com wrote: I admit I don't know exactly how MVars are implemented, but given that they can be aliased and have indefinite extent, I would think that they look something vaguely like a cdatatype ** var, basically a pointer to an MVar (which is itself a pointer, modulo some other things such as a thread queue.) And, I would think that unpacking such an structure would basically be eliminating one layer of indirection, so it would then look vague like a cdatatype * var.But again, given aliasing and indefinite extent, this would seem to be a difficult thing to do. Actually this isn't too difficult if an MVar only exists in a single unpacked structure: other references to the MVar can simply be pointers into the structure. But the case where an MVar is unpacked into two different structures suggests that, at least in some cases, an unpacked MVar is still a cdatatype ** var; So, is my understanding more or less correct? Does anybody have a good, succinct explanation of how MVars are implemented, and how they are unpacked? One final question, assuming that unpacking an MVar really does eliminate a layer of indirection, and that other references to that MVar are simply pointers into a larger structure, what happens to that larger structure when there are no more references to it (but still some references to the MVar?)Given the complications that must arise out of a doubly unpacked MVar, I'm going to guess that the larger structure does get garbage collected in this case, and that the MVar becomes dislodged from this structure. Would that MVar then be placed directly inside another unpacked reference, if one is available? Best, Leon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What does unpacking an MVar really mean?
Let me clarify a bit. I am familiar with the source of Control.Concurrent.MVar, and I do see {-# UNPACK #-}'ed MVars around, for example in GHC's IO manager. What I should have asked is, what does an MVar# look like? This cannot be inferred from Haskell source; though I suppose I could have tried to read the Runtime source. Now, one would hope that and (MVar# RealWorld footype) would approximately correspond to a footype * mvar; variable in C. The problem is this cannot _always_ be the case, because you can alias the (MVar# RealWorld footype) by placing a single MVar into two unpacked columns in two different data structures.So you would need to be able to still sometimes represent an MVar# by a footype ** mvar at runtime, even though one would hope that it would be represented by a footype * mvar in one particular data structure. On Tue, Jul 31, 2012 at 1:04 AM, Ryan Ingram ryani.s...@gmail.com wrote: Because of this, boxed MVars can be garbage collected without necessarily garbage-collecting the MVar# it holds, if a live reference to that MVar# still exists elsewhere. I was asking the dual question: if the MVar# exists in some data structure, can that data structure still be garbage collected when there is a reference to the MVar#, but not the data structure it is contained within. Best, Leon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] What is the surefire way to handle all exceptions and make sure the program doesn't fail?
First of all, apologise if the question is too broad. The background goes like this: I've implemented a server program in Haskell for my company intended to replace the previous one written in C which crashes a lot (and btw the technology of the company is exclusively C-based). When I chose Haskell I promised my manager (arrogantly - I actually made a bet with him), it won't crash. Now it has been finished (with just a few hundred LOC), and my test shows that it is indeed very stable. But by looking at the code again I'm a little worried, since I'm rather new to exception handling and there're many networking-related functions in the program. I was tempted to catch (SomeException e) at the very top-level of the program and try to recursively call main to restart the server in case of any exception being thrown, but I highly doubt that is the correct and idiomatic way. There are also a number of long-running threads launched from the main thread, and exceptions thrown from these threads can't be caught by the top-level `catch' in the main thread. My main function looks like this: main :: IO () main = withSocketsDo $ do sCameraU - socketNewPassive False 6000 sStunU - socketNewPassive False 3478 sCmdT- socketNewPassive True 7000 mvarCam - newMVar M.empty mvarLog - newMVar [] forkIO $ regCamera sCameraU mvarCam mvarLog forkIO $ updCamera mvarCam mvarLog forkIO $ stun sCameraU sStunU mvarCam mvarLog listen sCmdT 128 processCmd sCmdT mvarCam mvarLog sClose sCameraU sClose sStunU sClose sCmdT I find that I can't tell whether a function will throw any exception at all, or what exceptions will be thrown, by looking at their documentation. I can only tell if I browse the source code. So the question is, how can I determine all the exceptions that can be thrown by a given function? And what is the best way to handle situations like this, with both the long-running threads and main thread need to be restarted whenever exceptions happen. Regards, Yifan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What is the surefire way to handle all exceptions and make sure the program doesn't fail?
On 07/17/2012 08:34 AM, Yifan Yu wrote: First of all, apologise if the question is too broad. The background goes like this: I've implemented a server program in Haskell for my company intended to replace the previous one written in C which crashes a lot (and btw the technology of the company is exclusively C-based). When I chose Haskell I promised my manager (arrogantly - I actually made a bet with him), it won't crash. Now it has been finished (with just a few hundred LOC), and my test shows that it is indeed very stable. But by looking at the code again I'm a little worried, since I'm rather new to exception handling and there're many networking-related functions in the program. I was tempted to catch (SomeException e) at the very top-level of the program and try to recursively call main to restart the server in case of any exception being thrown, but I highly doubt that is the correct and idiomatic way. There are also a number of long-running threads launched from the main thread, and exceptions thrown from these threads can't be caught by the top-level `catch' in the main thread. My main function looks like this: [--snip--] I find that I can't tell whether a function will throw any exception at all, or what exceptions will be thrown, by looking at their documentation. I can only tell if I browse the source code. So the question is, how can I determine all the exceptions that can be thrown by a given function? Look at its source. And what is the best way to handle situations like this, with both the long-running threads and main thread need to be restarted whenever exceptions happen. The most robust way is probably to use a completely independent supervisor program, e.g. upstart, systemd, runit, etc. These usually have facilities for restarting the supervised program, and a rate limit on exactly how often to try that (over a given period of time). These *won't* work for a program that's deadlocked because an important thread has died. For that you'll need either a watchdog (external) or an in-program mechanism for supervised threads which can catch any and all exceptions and restart threads as necessary. This tends to very domain-specific, but you might take some inspiration for the way supervisor hierarchies work in the actor model. Regards, ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What is the surefire way to handle all exceptions and make sure the program doesn't fail?
On 17 July 2012 22:10, Bardur Arantsson s...@scientician.net wrote: On 07/17/2012 08:34 AM, Yifan Yu wrote: I can only tell if I browse the source code. So the question is, how can I determine all the exceptions that can be thrown by a given function? Look at its source. Not sure that's the most productive comment. ;-P ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What is the surefire way to handle all exceptions and make sure the program doesn't fail?
On 07/17/2012 10:17 PM, Christopher Done wrote: On 17 July 2012 22:10, Bardur Arantsson s...@scientician.net wrote: On 07/17/2012 08:34 AM, Yifan Yu wrote: I can only tell if I browse the source code. So the question is, how can I determine all the exceptions that can be thrown by a given function? Look at its source. Not sure that's the most productive comment. ;-P Well, it's either that or the documentation, and if you want to be *really* sure... (I did realize that the OP did mention looking at the source, I just thought I'd confirm. I hope it didn't come out snarky -- I certainly didn't intend it to.) Regards, ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What is the surefire way to handle all exceptions and make sure the program doesn't fail?
Hello there Yifan, exception handling should be done on a per-context basis, where the developer establishes the notion of context. Most of the time this boils down to releasing resources: forkIO (doStuffWith h `finally` hClose h) In more complicated scenarios, where you actually need to /handle/ the exception you should probably wrap some control concept around it. There are many options. You could just catch and handle the exception. Other options include a resumable monad (like monad-coroutine) that brings everything back into a consistent state. Exception handling is convenient in Haskell. You should probably just try to enforce some of the exception cases by using the server in a wrong way. Close the connection prematurely or send Unix signals. Note that you need to handle signals separately. In particular by default a SIGPIPE, which can in fact be thrown by the networking system, needs to be ignored: import System.Posix.Signal main :: IO () main = withSocketsDo $ do installHandler sigPIPE Ignore Nothing Finally for both efficiency and safety make use of a stream processing abstraction like conduit, enumerator or pipes. Greets, Ertugrul Yifan Yu yvi...@gmail.com wrote: First of all, apologise if the question is too broad. The background goes like this: I've implemented a server program in Haskell for my company intended to replace the previous one written in C which crashes a lot (and btw the technology of the company is exclusively C-based). When I chose Haskell I promised my manager (arrogantly - I actually made a bet with him), it won't crash. Now it has been finished (with just a few hundred LOC), and my test shows that it is indeed very stable. But by looking at the code again I'm a little worried, since I'm rather new to exception handling and there're many networking-related functions in the program. I was tempted to catch (SomeException e) at the very top-level of the program and try to recursively call main to restart the server in case of any exception being thrown, but I highly doubt that is the correct and idiomatic way. There are also a number of long-running threads launched from the main thread, and exceptions thrown from these threads can't be caught by the top-level `catch' in the main thread. My main function looks like this: main :: IO () main = withSocketsDo $ do sCameraU - socketNewPassive False 6000 sStunU - socketNewPassive False 3478 sCmdT- socketNewPassive True 7000 mvarCam - newMVar M.empty mvarLog - newMVar [] forkIO $ regCamera sCameraU mvarCam mvarLog forkIO $ updCamera mvarCam mvarLog forkIO $ stun sCameraU sStunU mvarCam mvarLog listen sCmdT 128 processCmd sCmdT mvarCam mvarLog sClose sCameraU sClose sStunU sClose sCmdT I find that I can't tell whether a function will throw any exception at all, or what exceptions will be thrown, by looking at their documentation. I can only tell if I browse the source code. So the question is, how can I determine all the exceptions that can be thrown by a given function? And what is the best way to handle situations like this, with both the long-running threads and main thread need to be restarted whenever exceptions happen. -- Not to be or to be and (not to be or to be and (not to be or to be and (not to be or to be and ... that is the list monad. signature.asc Description: PGP signature ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What is the surefire way to handle all exceptions and make sure the program doesn't fail?
On Wed, Jul 18, 2012 at 4:10 AM, Bardur Arantsson s...@scientician.netwrote: The most robust way is probably to use a completely independent supervisor program, e.g. upstart, systemd, runit, etc. These usually have facilities for restarting the supervised program, and a rate limit on exactly how often to try that (over a given period of time). These *won't* work for a program that's deadlocked because an important thread has died. For that you'll need either a watchdog (external) or an in-program mechanism for supervised threads which can catch any and all exceptions and restart threads as necessary. This tends to very domain-specific, but you might take some inspiration for the way supervisor hierarchies work in the actor model. Hi Bardur, the supervised threads sounds like a good approach for me. Thanks! ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What is the surefire way to handle all exceptions and make sure the program doesn't fail?
On Wed, Jul 18, 2012 at 7:05 AM, Ertugrul Söylemez e...@ertes.de wrote: exception handling should be done on a per-context basis, where the developer establishes the notion of context. Most of the time this boils down to releasing resources: forkIO (doStuffWith h `finally` hClose h) Hello Ertugrul, Agreed, although sometimes I just want to be lazy and catch any exception and see what it is in the top-level context :-) In more complicated scenarios, where you actually need to /handle/ the exception you should probably wrap some control concept around it. There are many options. You could just catch and handle the exception. Other options include a resumable monad (like monad-coroutine) that brings everything back into a consistent state. Finally for both efficiency and safety make use of a stream processing abstraction like conduit, enumerator or pipes. Thank you for these interesting pointers, I'll look into them later. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What is the difference between runhaskell and compile?
Have found the place in openldap where the error occurs, but do not know why. Please refer to http://hackage.haskell.org/trac/ghc/ticket/6128 . On Thu, Jul 12, 2012 at 2:03 PM, Magicloud Magiclouds magicloud.magiclo...@gmail.com wrote: I made a little code, to explicitly use unbind: ldapWith :: String - LDAPInt - (LDAP - IO a) - IO a ldapWith host port f = withCString host $ \cs - do cld - cldap_init cs port ptr - checkNULL ldapWith (return cld) rv - newForeignPtr_ ptr ldapSetVersion3 cld a - f rv _ - cldap_unbind cld return a And it gave me another packet data. Sec 11 is runhaskell, Sec 15 is binary (failed). The failed one has a FIN, ACK, weird. LDAP-0.6.6 is a binding to c library without any other haskell library except base, I think how ghc works should not effect its internal network operation On Thu, Jul 12, 2012 at 10:14 AM, Magicloud Magiclouds magicloud.magiclo...@gmail.com wrote: Dug a little more. Seems that ghc 7.4.* finalizes (ldap_unbind action) the ldap ptr before the references were actually dropped. On Thu, Jul 12, 2012 at 9:41 AM, Magicloud Magiclouds magicloud.magiclo...@gmail.com wrote: Sorry for the attachments. They are wireshark files. On Thu, Jul 12, 2012 at 9:35 AM, Magicloud Magiclouds magicloud.magiclo...@gmail.com wrote: OK. Finally this problem totally prevents my project from working. By some guy's suggestion, I did a packet capturing, which really showed a difference. The rwdc file is for a ldap that at our IDC, which did not work with compiled binary. The rodc file is for a ldap that at local, which worked all the time. Each file contains two parts of records, at 3.* sec and 6/7.* sec. The 3.* part is for runhaskell way. The 6/7.* part is for compiled binary way. The big difference here is: the failed one sent unbindRequest before got bindResponse success. Just a clue, I have no idea what is going on On Fri, Jun 1, 2012 at 5:17 PM, Chris Dornan ch...@chrisdornan.com wrote: No problem -- I have attached the executable too. Chris -Original Message- From: Magicloud Magiclouds [mailto:magicloud.magiclo...@gmail.com] Sent: 01 June 2012 02:01 To: Chris Dornan Subject: Re: [Haskell-cafe] What is the difference between runhaskell and compile? I see. Although I am using a UTF-8 environment, but all string I was using were ASCIIs. If it is not too much trouble, may I have your LDAP compiled library files? I think since the Main.o is identical, maybe the libraries are different. On Thu, May 31, 2012 at 2:09 PM, Chris Dornan ch...@chrisdornan.com wrote: I wouldn't pay too much attention to the fact that the hash tags are different -- they are very unlikely to be the same across two installations. (For example, my GHC installations are relocated under /usr/hs, immediately changing the contents of all of the .conf files and therefore the hashes.) The object files are more interesting, and they are identical! At the moment I can only explain what we are seeing by assuming that some change has affected the GHC 7.4.1 runtime system -- but only for compiled programs. Are you using non-ASCII characters in your LDAP passwords? I am thinking that maybe the compiled 7.4.1 could be using a different LOCALE from everything else, leading in some way to the passwords being encoded differently en route to the LDAP server. I don't know whether this could actually happen, but it is the kind of mechanism that seem most likely to be causing the problem. Did you try to running the variants that read address, account and passwords from standard input? Did it show the same perverse behaviour? Chris -Original Message- From: Magicloud Magiclouds [mailto:magicloud.magiclo...@gmail.com] Sent: 31 May 2012 02:47 To: Chris Dornan Subject: Re: [Haskell-cafe] What is the difference between runhaskell and compile? Hi, I have compared the files. The .o-es are exactly the same. The .hi-s are different. The interface hash, flag hash, and import -/ LDAP-0.6.6:LDAP.Constants x(hash) are different. I do not know why only this module (LDAP.Constants) has a different hash. I am not quite familiar with ghc compiling process. May I know your conclusion? On Wed, May 30, 2012 at 3:50 PM, Chris Dornan ch...@chrisdornan.com wrote: Did you carry out a standard (optimised) build to get ghc-7.4.1? Are you going to try the justhub rpms or compare the object/header files I sent. Chris -Original Message- From: Magicloud Magiclouds [mailto:magicloud.magiclo...@gmail.com] Sent: 30 May 2012 04:07 To: Chris Dornan Cc: Haskell-Cafe Subject: Re: [Haskell-cafe] What is the difference between runhaskell and compile? A little information. I did not notice the gcc/binutils versions. But in CentOS, the ghc 7.2.2/7.4.1 were all compiled myself with all default configurations. On Tue, May 29, 2012 at 10
Re: [Haskell-cafe] What is the difference between runhaskell and compile?
On Thu, Jul 12, 2012 at 09:41:43AM +0800, Magicloud Magiclouds wrote: Sorry for the attachments. They are wireshark files. May I suggest not sending multi-megabyte files of limited interest down a widely subscribed list? Contrary to popular belief, bandwidth, time and spool storage isn't free. It might be a very good idea to take those off-list. -- Lars Viklund | z...@acc.umu.se ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What is the difference between runhaskell and compile?
Sorry for that. The problem got solved yesterday. On Mon, Jul 16, 2012 at 6:01 PM, Lars Viklund z...@acc.umu.se wrote: On Thu, Jul 12, 2012 at 09:41:43AM +0800, Magicloud Magiclouds wrote: Sorry for the attachments. They are wireshark files. May I suggest not sending multi-megabyte files of limited interest down a widely subscribed list? Contrary to popular belief, bandwidth, time and spool storage isn't free. It might be a very good idea to take those off-list. -- Lars Viklund | z...@acc.umu.se ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- 竹密岂妨流水过 山高哪阻野云飞 And for G+, please use magiclouds#gmail.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What is the difference between runhaskell and compile?
OK. Finally this problem totally prevents my project from working. By some guy's suggestion, I did a packet capturing, which really showed a difference. The rwdc file is for a ldap that at our IDC, which did not work with compiled binary. The rodc file is for a ldap that at local, which worked all the time. Each file contains two parts of records, at 3.* sec and 6/7.* sec. The 3.* part is for runhaskell way. The 6/7.* part is for compiled binary way. The big difference here is: the failed one sent unbindRequest before got bindResponse success. Just a clue, I have no idea what is going on On Fri, Jun 1, 2012 at 5:17 PM, Chris Dornan ch...@chrisdornan.com wrote: No problem -- I have attached the executable too. Chris -Original Message- From: Magicloud Magiclouds [mailto:magicloud.magiclo...@gmail.com] Sent: 01 June 2012 02:01 To: Chris Dornan Subject: Re: [Haskell-cafe] What is the difference between runhaskell and compile? I see. Although I am using a UTF-8 environment, but all string I was using were ASCIIs. If it is not too much trouble, may I have your LDAP compiled library files? I think since the Main.o is identical, maybe the libraries are different. On Thu, May 31, 2012 at 2:09 PM, Chris Dornan ch...@chrisdornan.com wrote: I wouldn't pay too much attention to the fact that the hash tags are different -- they are very unlikely to be the same across two installations. (For example, my GHC installations are relocated under /usr/hs, immediately changing the contents of all of the .conf files and therefore the hashes.) The object files are more interesting, and they are identical! At the moment I can only explain what we are seeing by assuming that some change has affected the GHC 7.4.1 runtime system -- but only for compiled programs. Are you using non-ASCII characters in your LDAP passwords? I am thinking that maybe the compiled 7.4.1 could be using a different LOCALE from everything else, leading in some way to the passwords being encoded differently en route to the LDAP server. I don't know whether this could actually happen, but it is the kind of mechanism that seem most likely to be causing the problem. Did you try to running the variants that read address, account and passwords from standard input? Did it show the same perverse behaviour? Chris -Original Message- From: Magicloud Magiclouds [mailto:magicloud.magiclo...@gmail.com] Sent: 31 May 2012 02:47 To: Chris Dornan Subject: Re: [Haskell-cafe] What is the difference between runhaskell and compile? Hi, I have compared the files. The .o-es are exactly the same. The .hi-s are different. The interface hash, flag hash, and import -/ LDAP-0.6.6:LDAP.Constants x(hash) are different. I do not know why only this module (LDAP.Constants) has a different hash. I am not quite familiar with ghc compiling process. May I know your conclusion? On Wed, May 30, 2012 at 3:50 PM, Chris Dornan ch...@chrisdornan.com wrote: Did you carry out a standard (optimised) build to get ghc-7.4.1? Are you going to try the justhub rpms or compare the object/header files I sent. Chris -Original Message- From: Magicloud Magiclouds [mailto:magicloud.magiclo...@gmail.com] Sent: 30 May 2012 04:07 To: Chris Dornan Cc: Haskell-Cafe Subject: Re: [Haskell-cafe] What is the difference between runhaskell and compile? A little information. I did not notice the gcc/binutils versions. But in CentOS, the ghc 7.2.2/7.4.1 were all compiled myself with all default configurations. On Tue, May 29, 2012 at 10:54 PM, Chris Dornan ch...@chrisdornan.com wrote: On 29 May 2012 02:21, Magicloud Magiclouds magicloud.magiclo...@gmail.com wrote: Interesting. I have this code tested in Debian unstable/stable, CentOS 6.1, all 64 bit, with two different version of libldap2. At first, Debian-s were installed with 7.4.1, CentOS with 7.2.2. Only in CentOS the code connected after compiled. Then I removed 7.4.1 from Debian stable and installed 7.2.2. The code worked. At last, I installed 7.4.1 in CentOS. The code did not work. Could you send the .hi/.o to me, so maybe I could find out the different? Also the exact original source. Thank you. Interesting indeed! I am guessing that you are using the GHC-7.4.1 bindist from haskell.org. I will try and find some time to marshal the source code and intermediate files (am on the road -- will need to collect it from base, make it generic etc.). You might also like to try the http://justhub.org ghc-7.4.1-hub on your CentOS-6.1 node. It is a separate build from the haskell.org bindist and comes with it's own in-board gcc (4.6.1) and binutils (2.21) used for the build. It should work for you. (You could also try ghc-7.4.2-RC1-hub.) Chris -- 竹密岂妨流水过 山高哪阻野云飞 And for G+, please use magiclouds#gmail.com. -- 竹密岂妨流水过 山高哪阻野云飞 And for G+, please use magiclouds#gmail.com. -- 竹密岂妨流水过 山高哪阻野云飞
Re: [Haskell-cafe] What is the difference between runhaskell and compile?
Dug a little more. Seems that ghc 7.4.* finalizes (ldap_unbind action) the ldap ptr before the references were actually dropped. On Thu, Jul 12, 2012 at 9:41 AM, Magicloud Magiclouds magicloud.magiclo...@gmail.com wrote: Sorry for the attachments. They are wireshark files. On Thu, Jul 12, 2012 at 9:35 AM, Magicloud Magiclouds magicloud.magiclo...@gmail.com wrote: OK. Finally this problem totally prevents my project from working. By some guy's suggestion, I did a packet capturing, which really showed a difference. The rwdc file is for a ldap that at our IDC, which did not work with compiled binary. The rodc file is for a ldap that at local, which worked all the time. Each file contains two parts of records, at 3.* sec and 6/7.* sec. The 3.* part is for runhaskell way. The 6/7.* part is for compiled binary way. The big difference here is: the failed one sent unbindRequest before got bindResponse success. Just a clue, I have no idea what is going on On Fri, Jun 1, 2012 at 5:17 PM, Chris Dornan ch...@chrisdornan.com wrote: No problem -- I have attached the executable too. Chris -Original Message- From: Magicloud Magiclouds [mailto:magicloud.magiclo...@gmail.com] Sent: 01 June 2012 02:01 To: Chris Dornan Subject: Re: [Haskell-cafe] What is the difference between runhaskell and compile? I see. Although I am using a UTF-8 environment, but all string I was using were ASCIIs. If it is not too much trouble, may I have your LDAP compiled library files? I think since the Main.o is identical, maybe the libraries are different. On Thu, May 31, 2012 at 2:09 PM, Chris Dornan ch...@chrisdornan.com wrote: I wouldn't pay too much attention to the fact that the hash tags are different -- they are very unlikely to be the same across two installations. (For example, my GHC installations are relocated under /usr/hs, immediately changing the contents of all of the .conf files and therefore the hashes.) The object files are more interesting, and they are identical! At the moment I can only explain what we are seeing by assuming that some change has affected the GHC 7.4.1 runtime system -- but only for compiled programs. Are you using non-ASCII characters in your LDAP passwords? I am thinking that maybe the compiled 7.4.1 could be using a different LOCALE from everything else, leading in some way to the passwords being encoded differently en route to the LDAP server. I don't know whether this could actually happen, but it is the kind of mechanism that seem most likely to be causing the problem. Did you try to running the variants that read address, account and passwords from standard input? Did it show the same perverse behaviour? Chris -Original Message- From: Magicloud Magiclouds [mailto:magicloud.magiclo...@gmail.com] Sent: 31 May 2012 02:47 To: Chris Dornan Subject: Re: [Haskell-cafe] What is the difference between runhaskell and compile? Hi, I have compared the files. The .o-es are exactly the same. The .hi-s are different. The interface hash, flag hash, and import -/ LDAP-0.6.6:LDAP.Constants x(hash) are different. I do not know why only this module (LDAP.Constants) has a different hash. I am not quite familiar with ghc compiling process. May I know your conclusion? On Wed, May 30, 2012 at 3:50 PM, Chris Dornan ch...@chrisdornan.com wrote: Did you carry out a standard (optimised) build to get ghc-7.4.1? Are you going to try the justhub rpms or compare the object/header files I sent. Chris -Original Message- From: Magicloud Magiclouds [mailto:magicloud.magiclo...@gmail.com] Sent: 30 May 2012 04:07 To: Chris Dornan Cc: Haskell-Cafe Subject: Re: [Haskell-cafe] What is the difference between runhaskell and compile? A little information. I did not notice the gcc/binutils versions. But in CentOS, the ghc 7.2.2/7.4.1 were all compiled myself with all default configurations. On Tue, May 29, 2012 at 10:54 PM, Chris Dornan ch...@chrisdornan.com wrote: On 29 May 2012 02:21, Magicloud Magiclouds magicloud.magiclo...@gmail.com wrote: Interesting. I have this code tested in Debian unstable/stable, CentOS 6.1, all 64 bit, with two different version of libldap2. At first, Debian-s were installed with 7.4.1, CentOS with 7.2.2. Only in CentOS the code connected after compiled. Then I removed 7.4.1 from Debian stable and installed 7.2.2. The code worked. At last, I installed 7.4.1 in CentOS. The code did not work. Could you send the .hi/.o to me, so maybe I could find out the different? Also the exact original source. Thank you. Interesting indeed! I am guessing that you are using the GHC-7.4.1 bindist from haskell.org. I will try and find some time to marshal the source code and intermediate files (am on the road -- will need to collect it from base, make it generic etc.). You might also like to try the http://justhub.org ghc-7.4.1-hub on your CentOS-6.1 node
Re: [Haskell-cafe] What extension do I need to write type Job = Map k a?
OK. I am totally confused here. Why Couldn't match expected type `Jobs k e a' with actual type `M.Map k0 b0' 9|data JobInfo a e = (Exception e) = 10| JobInfo { jobId :: ThreadId 11| , result :: MVar (Either e a) } 12| 13|type Jobs k e a = (Ord k, Exception e) = 14| M.Map k (JobInfo e a) 15| 16|type JobArgs k a = (Ord k) = 17| M.Map k a 21| 22|start :: (Ord k, Exception e) = JobArgs k a - (a - IO b) - IO (Jobs k e a) 23|start args worker = do 24| arg - newEmptyMVar 25| Map.mapM (\a - do 26| putMVar arg a 27| result - newEmptyMVar 28| tId - forkIO $ do 29| arg_ - takeMVar arg 30| result_ - try $ worker arg_ 31| putMVar result result_ 32| return $ JobInfo tId result 33| ) args On Thu, Jun 14, 2012 at 1:24 PM, Magicloud Magiclouds magicloud.magiclo...@gmail.com wrote: I think I need to think this through On Thu, Jun 14, 2012 at 12:28 PM, Ivan Lazar Miljenovic ivan.miljeno...@gmail.com wrote: On 14 June 2012 14:20, Magicloud Magiclouds magicloud.magiclo...@gmail.com wrote: OK. I think I understand a little. I use Job here just wants to simplify the code. And since I provide the function as library, I cannot decide what exact type k is. What should I do? Do you know what the type of `a'? If so: type Job k = Map k String Otherwise... do you even need a type alias? On Thu, Jun 14, 2012 at 11:23 AM, Arlen Cuss a...@len.me wrote: (resending to café, turns out I wasn't subbed from this address.) Hi Magicloud, This is correct; because you've hidden the type-variables away by universally quantifying them, there's no more level of specificity you can get back *out* of them than just some kind of Map (Job = M.Map k b, where k ≠ k0, b ≠ b0). If you have a Job type which can store *any* kind of Map (forall k a. Job (Map k a)), then that means you could have a Job with a Map Int Bool, and a Job with a Map String (Float - Float), and they'd both have the same type Job. You can't do anything with the values within, because you're being too permissive about what a Job is. You may want data Job k a = Job (Map k a), *or* if you do actually use one kind of Map only, then why not data Job = Job (Map Int String) (substituting your real types for Int and String). In this case, you could also consider using newtype (newtype Job = Job { getJob :: Map Int String }) to provide the guarantee that you're getting a Job (and not any Map Int String) without performance loss. Let me know if I've been more confusing than helpful; Arlen On Thursday, 14 June 2012 at 1:16 PM, Magicloud Magiclouds wrote: Hi there, Thanks for the reply. To be clear, all I want is to avoid having to type type variables all over the place. What should I do? My original code with RankNTypes and ImpredicativeTypes does not work The type Job = forall k a. M.Map k a works now. But function uses it does not. Compiler complains about Couldn't match expected type `Job' with actual type `M.Map k0 b0'. On Wed, Jun 13, 2012 at 9:15 PM, Daniel Peebles pumpkin...@gmail.com (mailto:pumpkin...@gmail.com) wrote: That doesn't require existential quantification, but it'll need Rank-2 typesif you ever do anything with Job. Unfortunately, a universally quantifiedJob like what you wrote (or what Magicloud seems to want) is only inhabitedby the empty Map. An existentially quantified Job, as you might get with data Job = forall k a. Job (Map k a) does let you wrap up any Map containing anything in it, but unfortunatelythe only thing you can do with that map afterwards is ask for structuralproperties about it, like whether it's empty or how many elements it has init. You could ask to enumerate the elements in it, but you wouldn't be ableto touch any of them because you wouldn't know what their types were. So I'm not really sure how to interpret the question. Was the goal to have aheterogeneous Map, maybe? Or just to avoid having to type type variables allover the place? Both of those are possible but require a bit moresophistication with types. -Dan On Wed, Jun 13, 2012 at 7:32 AM, Ismael Figueroa Paletifiguer...@gmail.com (mailto:ifiguer...@gmail.com) wrote: Do you want to hide the specific types of the job? Presumably to thendefine a type JobList = [Job] ?You can do that with the ExistentialQuantification extension. type Job = forall k a. Map k atype JobList = [Job] ??Note you can't unpack the types k a once you have hidden them. But thetypechecker can use it to ensure some static property.Also you could use unsafeCoerce to do some casts, but *only if you are*sure* that things will go OK*. 2012/6/13 Magicloud Magiclouds magicloud.magiclo...@gmail.com (mailto:magicloud.magiclo...@gmail.com) Hi,I've forgotten this.This is OK:type Job k a = Map k
Re: [Haskell-cafe] What extension do I need to write type Job = Map k a?
Sorry, the last 'a' of line 22 is 'b'. On Thu, Jun 14, 2012 at 3:19 PM, Magicloud Magiclouds magicloud.magiclo...@gmail.com wrote: OK. I am totally confused here. Why Couldn't match expected type `Jobs k e a' with actual type `M.Map k0 b0' 9|data JobInfo a e = (Exception e) = 10| JobInfo { jobId :: ThreadId 11| , result :: MVar (Either e a) } 12| 13|type Jobs k e a = (Ord k, Exception e) = 14| M.Map k (JobInfo e a) 15| 16|type JobArgs k a = (Ord k) = 17| M.Map k a 21| 22|start :: (Ord k, Exception e) = JobArgs k a - (a - IO b) - IO (Jobs k e a) 23|start args worker = do 24| arg - newEmptyMVar 25| Map.mapM (\a - do 26| putMVar arg a 27| result - newEmptyMVar 28| tId - forkIO $ do 29| arg_ - takeMVar arg 30| result_ - try $ worker arg_ 31| putMVar result result_ 32| return $ JobInfo tId result 33| ) args On Thu, Jun 14, 2012 at 1:24 PM, Magicloud Magiclouds magicloud.magiclo...@gmail.com wrote: I think I need to think this through On Thu, Jun 14, 2012 at 12:28 PM, Ivan Lazar Miljenovic ivan.miljeno...@gmail.com wrote: On 14 June 2012 14:20, Magicloud Magiclouds magicloud.magiclo...@gmail.com wrote: OK. I think I understand a little. I use Job here just wants to simplify the code. And since I provide the function as library, I cannot decide what exact type k is. What should I do? Do you know what the type of `a'? If so: type Job k = Map k String Otherwise... do you even need a type alias? On Thu, Jun 14, 2012 at 11:23 AM, Arlen Cuss a...@len.me wrote: (resending to café, turns out I wasn't subbed from this address.) Hi Magicloud, This is correct; because you've hidden the type-variables away by universally quantifying them, there's no more level of specificity you can get back *out* of them than just some kind of Map (Job = M.Map k b, where k ≠ k0, b ≠ b0). If you have a Job type which can store *any* kind of Map (forall k a. Job (Map k a)), then that means you could have a Job with a Map Int Bool, and a Job with a Map String (Float - Float), and they'd both have the same type Job. You can't do anything with the values within, because you're being too permissive about what a Job is. You may want data Job k a = Job (Map k a), *or* if you do actually use one kind of Map only, then why not data Job = Job (Map Int String) (substituting your real types for Int and String). In this case, you could also consider using newtype (newtype Job = Job { getJob :: Map Int String }) to provide the guarantee that you're getting a Job (and not any Map Int String) without performance loss. Let me know if I've been more confusing than helpful; Arlen On Thursday, 14 June 2012 at 1:16 PM, Magicloud Magiclouds wrote: Hi there, Thanks for the reply. To be clear, all I want is to avoid having to type type variables all over the place. What should I do? My original code with RankNTypes and ImpredicativeTypes does not work The type Job = forall k a. M.Map k a works now. But function uses it does not. Compiler complains about Couldn't match expected type `Job' with actual type `M.Map k0 b0'. On Wed, Jun 13, 2012 at 9:15 PM, Daniel Peebles pumpkin...@gmail.com (mailto:pumpkin...@gmail.com) wrote: That doesn't require existential quantification, but it'll need Rank-2 typesif you ever do anything with Job. Unfortunately, a universally quantifiedJob like what you wrote (or what Magicloud seems to want) is only inhabitedby the empty Map. An existentially quantified Job, as you might get with data Job = forall k a. Job (Map k a) does let you wrap up any Map containing anything in it, but unfortunatelythe only thing you can do with that map afterwards is ask for structuralproperties about it, like whether it's empty or how many elements it has init. You could ask to enumerate the elements in it, but you wouldn't be ableto touch any of them because you wouldn't know what their types were. So I'm not really sure how to interpret the question. Was the goal to have aheterogeneous Map, maybe? Or just to avoid having to type type variables allover the place? Both of those are possible but require a bit moresophistication with types. -Dan On Wed, Jun 13, 2012 at 7:32 AM, Ismael Figueroa Paletifiguer...@gmail.com (mailto:ifiguer...@gmail.com) wrote: Do you want to hide the specific types of the job? Presumably to thendefine a type JobList = [Job] ?You can do that with the ExistentialQuantification extension. type Job = forall k a. Map k atype JobList = [Job] ??Note you can't unpack the types k a once you have hidden them. But thetypechecker can use it to ensure some static property.Also you could use unsafeCoerce to do some casts, but *only if you are*sure* that things will go OK*.
Re: [Haskell-cafe] What extension do I need to write type Job = Map k a?
And line 14, should be JobInfo a e. I must be too sleepy On Thu, Jun 14, 2012 at 3:30 PM, Magicloud Magiclouds magicloud.magiclo...@gmail.com wrote: Sorry, the last 'a' of line 22 is 'b'. On Thu, Jun 14, 2012 at 3:19 PM, Magicloud Magiclouds magicloud.magiclo...@gmail.com wrote: OK. I am totally confused here. Why Couldn't match expected type `Jobs k e a' with actual type `M.Map k0 b0' 9|data JobInfo a e = (Exception e) = 10| JobInfo { jobId :: ThreadId 11| , result :: MVar (Either e a) } 12| 13|type Jobs k e a = (Ord k, Exception e) = 14| M.Map k (JobInfo e a) 15| 16|type JobArgs k a = (Ord k) = 17| M.Map k a 21| 22|start :: (Ord k, Exception e) = JobArgs k a - (a - IO b) - IO (Jobs k e a) 23|start args worker = do 24| arg - newEmptyMVar 25| Map.mapM (\a - do 26| putMVar arg a 27| result - newEmptyMVar 28| tId - forkIO $ do 29| arg_ - takeMVar arg 30| result_ - try $ worker arg_ 31| putMVar result result_ 32| return $ JobInfo tId result 33| ) args On Thu, Jun 14, 2012 at 1:24 PM, Magicloud Magiclouds magicloud.magiclo...@gmail.com wrote: I think I need to think this through On Thu, Jun 14, 2012 at 12:28 PM, Ivan Lazar Miljenovic ivan.miljeno...@gmail.com wrote: On 14 June 2012 14:20, Magicloud Magiclouds magicloud.magiclo...@gmail.com wrote: OK. I think I understand a little. I use Job here just wants to simplify the code. And since I provide the function as library, I cannot decide what exact type k is. What should I do? Do you know what the type of `a'? If so: type Job k = Map k String Otherwise... do you even need a type alias? On Thu, Jun 14, 2012 at 11:23 AM, Arlen Cuss a...@len.me wrote: (resending to café, turns out I wasn't subbed from this address.) Hi Magicloud, This is correct; because you've hidden the type-variables away by universally quantifying them, there's no more level of specificity you can get back *out* of them than just some kind of Map (Job = M.Map k b, where k ≠ k0, b ≠ b0). If you have a Job type which can store *any* kind of Map (forall k a. Job (Map k a)), then that means you could have a Job with a Map Int Bool, and a Job with a Map String (Float - Float), and they'd both have the same type Job. You can't do anything with the values within, because you're being too permissive about what a Job is. You may want data Job k a = Job (Map k a), *or* if you do actually use one kind of Map only, then why not data Job = Job (Map Int String) (substituting your real types for Int and String). In this case, you could also consider using newtype (newtype Job = Job { getJob :: Map Int String }) to provide the guarantee that you're getting a Job (and not any Map Int String) without performance loss. Let me know if I've been more confusing than helpful; Arlen On Thursday, 14 June 2012 at 1:16 PM, Magicloud Magiclouds wrote: Hi there, Thanks for the reply. To be clear, all I want is to avoid having to type type variables all over the place. What should I do? My original code with RankNTypes and ImpredicativeTypes does not work The type Job = forall k a. M.Map k a works now. But function uses it does not. Compiler complains about Couldn't match expected type `Job' with actual type `M.Map k0 b0'. On Wed, Jun 13, 2012 at 9:15 PM, Daniel Peebles pumpkin...@gmail.com (mailto:pumpkin...@gmail.com) wrote: That doesn't require existential quantification, but it'll need Rank-2 typesif you ever do anything with Job. Unfortunately, a universally quantifiedJob like what you wrote (or what Magicloud seems to want) is only inhabitedby the empty Map. An existentially quantified Job, as you might get with data Job = forall k a. Job (Map k a) does let you wrap up any Map containing anything in it, but unfortunatelythe only thing you can do with that map afterwards is ask for structuralproperties about it, like whether it's empty or how many elements it has init. You could ask to enumerate the elements in it, but you wouldn't be ableto touch any of them because you wouldn't know what their types were. So I'm not really sure how to interpret the question. Was the goal to have aheterogeneous Map, maybe? Or just to avoid having to type type variables allover the place? Both of those are possible but require a bit moresophistication with types. -Dan On Wed, Jun 13, 2012 at 7:32 AM, Ismael Figueroa Paletifiguer...@gmail.com (mailto:ifiguer...@gmail.com) wrote: Do you want to hide the specific types of the job? Presumably to thendefine a type JobList = [Job] ?You can do that with the ExistentialQuantification extension. type Job = forall k a. Map k atype JobList = [Job] ??Note you can't unpack the types k a once you have hidden them. But thetypechecker can
Re: [Haskell-cafe] What extension do I need to write type Job = Map k a?
Hi Magicloud, The indentation has been lost in the mail. Could you post your code (preferably without line numbers) on hpaste.org or similar? —A On Thursday, 14 June 2012 at 5:33 PM, Magicloud Magiclouds wrote: And line 14, should be JobInfo a e. I must be too sleepy On Thu, Jun 14, 2012 at 3:30 PM, Magicloud Magiclouds magicloud.magiclo...@gmail.com (mailto:magicloud.magiclo...@gmail.com) wrote: Sorry, the last 'a' of line 22 is 'b'. On Thu, Jun 14, 2012 at 3:19 PM, Magicloud Magiclouds magicloud.magiclo...@gmail.com (mailto:magicloud.magiclo...@gmail.com) wrote: OK. I am totally confused here. Why Couldn't match expected type `Jobs k e a' with actual type `M.Map k0 b0' 9|data JobInfo a e = (Exception e) = 10| JobInfo { jobId :: ThreadId 11| , result :: MVar (Either e a) } 12| 13|type Jobs k e a = (Ord k, Exception e) = 14| M.Map k (JobInfo e a) 15| 16|type JobArgs k a = (Ord k) = 17| M.Map k a 21| 22|start :: (Ord k, Exception e) = JobArgs k a - (a - IO b) - IO (Jobs k e a) 23|start args worker = do 24| arg - newEmptyMVar 25| Map.mapM (\a - do 26| putMVar arg a 27| result - newEmptyMVar 28| tId - forkIO $ do 29| arg_ - takeMVar arg 30| result_ - try $ worker arg_ 31| putMVar result result_ 32| return $ JobInfo tId result 33| ) args On Thu, Jun 14, 2012 at 1:24 PM, Magicloud Magiclouds magicloud.magiclo...@gmail.com (mailto:magicloud.magiclo...@gmail.com) wrote: I think I need to think this through On Thu, Jun 14, 2012 at 12:28 PM, Ivan Lazar Miljenovic ivan.miljeno...@gmail.com (mailto:ivan.miljeno...@gmail.com) wrote: On 14 June 2012 14:20, Magicloud Magiclouds magicloud.magiclo...@gmail.com (mailto:magicloud.magiclo...@gmail.com) wrote: OK. I think I understand a little. I use Job here just wants to simplify the code. And since I provide the function as library, I cannot decide what exact type k is. What should I do? Do you know what the type of `a'? If so: type Job k = Map k String Otherwise... do you even need a type alias? On Thu, Jun 14, 2012 at 11:23 AM, Arlen Cuss a...@len.me (mailto:a...@len.me) wrote: (resending to café, turns out I wasn't subbed from this address.) Hi Magicloud, This is correct; because you've hidden the type-variables away by universally quantifying them, there's no more level of specificity you can get back *out* of them than just some kind of Map (Job = M.Map k b, where k ≠ k0, b ≠ b0). If you have a Job type which can store *any* kind of Map (forall k a. Job (Map k a)), then that means you could have a Job with a Map Int Bool, and a Job with a Map String (Float - Float), and they'd both have the same type Job. You can't do anything with the values within, because you're being too permissive about what a Job is. You may want data Job k a = Job (Map k a), *or* if you do actually use one kind of Map only, then why not data Job = Job (Map Int String) (substituting your real types for Int and String). In this case, you could also consider using newtype (newtype Job = Job { getJob :: Map Int String }) to provide the guarantee that you're getting a Job (and not any Map Int String) without performance loss. Let me know if I've been more confusing than helpful; Arlen On Thursday, 14 June 2012 at 1:16 PM, Magicloud Magiclouds wrote: Hi there, Thanks for the reply. To be clear, all I want is to avoid having to type type variables all over the place. What should I do? My original code with RankNTypes and ImpredicativeTypes does not work The type Job = forall k a. M.Map k a works now. But function uses it does not. Compiler complains about Couldn't match expected type `Job' with actual type `M.Map k0 b0'. On Wed, Jun 13, 2012 at 9:15 PM, Daniel Peebles pumpkin...@gmail.com (mailto:pumpkin...@gmail.com) wrote: That doesn't require existential quantification, but it'll need Rank-2 typesif you ever do anything with Job. Unfortunately, a universally quantifiedJob like what you wrote (or what Magicloud seems to want) is only inhabitedby the empty Map. An existentially quantified Job, as you might get with data Job = forall k a. Job (Map k a) does let you wrap up any Map containing anything in it, but unfortunatelythe only thing you can do with that map afterwards is ask for structuralproperties about it, like whether it's
Re: [Haskell-cafe] What extension do I need to write type Job = Map k a?
Sorry, the full code is here: http://hpaste.org/69972 On Fri, Jun 15, 2012 at 7:09 AM, Arlen Cuss a...@len.me wrote: Hi Magicloud, The indentation has been lost in the mail. Could you post your code (preferably without line numbers) on hpaste.org or similar? —A On Thursday, 14 June 2012 at 5:33 PM, Magicloud Magiclouds wrote: And line 14, should be JobInfo a e. I must be too sleepy On Thu, Jun 14, 2012 at 3:30 PM, Magicloud Magiclouds magicloud.magiclo...@gmail.com (mailto:magicloud.magiclo...@gmail.com) wrote: Sorry, the last 'a' of line 22 is 'b'. On Thu, Jun 14, 2012 at 3:19 PM, Magicloud Magiclouds magicloud.magiclo...@gmail.com (mailto:magicloud.magiclo...@gmail.com) wrote: OK. I am totally confused here. Why Couldn't match expected type `Jobs k e a' with actual type `M.Map k0 b0' 9|data JobInfo a e = (Exception e) = 10| JobInfo { jobId :: ThreadId 11| , result :: MVar (Either e a) } 12| 13|type Jobs k e a = (Ord k, Exception e) = 14| M.Map k (JobInfo e a) 15| 16|type JobArgs k a = (Ord k) = 17| M.Map k a 21| 22|start :: (Ord k, Exception e) = JobArgs k a - (a - IO b) - IO (Jobs k e a) 23|start args worker = do 24| arg - newEmptyMVar 25| Map.mapM (\a - do 26| putMVar arg a 27| result - newEmptyMVar 28| tId - forkIO $ do 29| arg_ - takeMVar arg 30| result_ - try $ worker arg_ 31| putMVar result result_ 32| return $ JobInfo tId result 33| ) args On Thu, Jun 14, 2012 at 1:24 PM, Magicloud Magiclouds magicloud.magiclo...@gmail.com (mailto:magicloud.magiclo...@gmail.com) wrote: I think I need to think this through On Thu, Jun 14, 2012 at 12:28 PM, Ivan Lazar Miljenovic ivan.miljeno...@gmail.com (mailto:ivan.miljeno...@gmail.com) wrote: On 14 June 2012 14:20, Magicloud Magiclouds magicloud.magiclo...@gmail.com (mailto:magicloud.magiclo...@gmail.com) wrote: OK. I think I understand a little. I use Job here just wants to simplify the code. And since I provide the function as library, I cannot decide what exact type k is. What should I do? Do you know what the type of `a'? If so: type Job k = Map k String Otherwise... do you even need a type alias? On Thu, Jun 14, 2012 at 11:23 AM, Arlen Cuss a...@len.me (mailto:a...@len.me) wrote: (resending to café, turns out I wasn't subbed from this address.) Hi Magicloud, This is correct; because you've hidden the type-variables away by universally quantifying them, there's no more level of specificity you can get back *out* of them than just some kind of Map (Job = M.Map k b, where k ≠ k0, b ≠ b0). If you have a Job type which can store *any* kind of Map (forall k a. Job (Map k a)), then that means you could have a Job with a Map Int Bool, and a Job with a Map String (Float - Float), and they'd both have the same type Job. You can't do anything with the values within, because you're being too permissive about what a Job is. You may want data Job k a = Job (Map k a), *or* if you do actually use one kind of Map only, then why not data Job = Job (Map Int String) (substituting your real types for Int and String). In this case, you could also consider using newtype (newtype Job = Job { getJob :: Map Int String }) to provide the guarantee that you're getting a Job (and not any Map Int String) without performance loss. Let me know if I've been more confusing than helpful; Arlen On Thursday, 14 June 2012 at 1:16 PM, Magicloud Magiclouds wrote: Hi there, Thanks for the reply. To be clear, all I want is to avoid having to type type variables all over the place. What should I do? My original code with RankNTypes and ImpredicativeTypes does not work The type Job = forall k a. M.Map k a works now. But function uses it does not. Compiler complains about Couldn't match expected type `Job' with actual type `M.Map k0 b0'. On Wed, Jun 13, 2012 at 9:15 PM, Daniel Peebles pumpkin...@gmail.com (mailto:pumpkin...@gmail.com) wrote: That doesn't require existential quantification, but it'll need Rank-2 typesif you ever do anything with Job. Unfortunately, a universally quantifiedJob like what you wrote (or what Magicloud seems to want) is only inhabitedby the empty Map. An existentially quantified Job, as you might get with data Job = forall k a. Job (Map k a) does let you wrap up any Map containing anything in it, but unfortunatelythe only thing you can do with that map
[Haskell-cafe] What extension do I need to write type Job = Map k a?
Hi, I've forgotten this. This is OK: type Job k a = Map k a And this is OK: {-# LANGUAGE RankNTypes #-} -- or LiberalTypeSynonyms? type Job = forall a. forall k. Map k a Then how to write it like this? type Job = Map k a -- 竹密岂妨流水过 山高哪阻野云飞 And for G+, please use magiclouds#gmail.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What extension do I need to write type Job = Map k a?
On 13 June 2012 19:59, Magicloud Magiclouds magicloud.magiclo...@gmail.com wrote: Hi, I've forgotten this. This is OK: type Job k a = Map k a And this is OK: {-# LANGUAGE RankNTypes #-} -- or LiberalTypeSynonyms? type Job = forall a. forall k. Map k a Then how to write it like this? type Job = Map k a Does that even make sense? What are the types of `k' and `a' in Job? -- Ivan Lazar Miljenovic ivan.miljeno...@gmail.com http://IvanMiljenovic.wordpress.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What extension do I need to write type Job = Map k a?
Do you want to hide the specific types of the job? Presumably to then define a type JobList = [Job] ? You can do that with the ExistentialQuantification extension. type Job = forall k a. Map k a type JobList = [Job] ?? Note you can't unpack the types k a once you have hidden them. But the typechecker can use it to ensure some static property. Also you could use unsafeCoerce to do some casts, but *only if you are *sure* that things will go OK*. 2012/6/13 Magicloud Magiclouds magicloud.magiclo...@gmail.com Hi, I've forgotten this. This is OK: type Job k a = Map k a And this is OK: {-# LANGUAGE RankNTypes #-} -- or LiberalTypeSynonyms? type Job = forall a. forall k. Map k a Then how to write it like this? type Job = Map k a -- 竹密岂妨流水过 山高哪阻野云飞 And for G+, please use magiclouds#gmail.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- Ismael ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What extension do I need to write type Job = Map k a?
That doesn't require existential quantification, but it'll need Rank-2 types if you ever do anything with Job. Unfortunately, a universally quantified Job like what you wrote (or what Magicloud seems to want) is only inhabited by the empty Map. An existentially quantified Job, as you might get with data Job = forall k a. Job (Map k a) does let you wrap up any Map containing anything in it, but unfortunately the only thing you can do with that map afterwards is ask for structural properties about it, like whether it's empty or how many elements it has in it. You could ask to enumerate the elements in it, but you wouldn't be able to touch any of them because you wouldn't know what their types were. So I'm not really sure how to interpret the question. Was the goal to have a heterogeneous Map, maybe? Or just to avoid having to type type variables all over the place? Both of those are possible but require a bit more sophistication with types. -Dan On Wed, Jun 13, 2012 at 7:32 AM, Ismael Figueroa Palet ifiguer...@gmail.com wrote: Do you want to hide the specific types of the job? Presumably to then define a type JobList = [Job] ? You can do that with the ExistentialQuantification extension. type Job = forall k a. Map k a type JobList = [Job] ?? Note you can't unpack the types k a once you have hidden them. But the typechecker can use it to ensure some static property. Also you could use unsafeCoerce to do some casts, but *only if you are *sure* that things will go OK*. 2012/6/13 Magicloud Magiclouds magicloud.magiclo...@gmail.com Hi, I've forgotten this. This is OK: type Job k a = Map k a And this is OK: {-# LANGUAGE RankNTypes #-} -- or LiberalTypeSynonyms? type Job = forall a. forall k. Map k a Then how to write it like this? type Job = Map k a -- 竹密岂妨流水过 山高哪阻野云飞 And for G+, please use magiclouds#gmail.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- Ismael ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What extension do I need to write type Job = Map k a?
Mmmmh... no, to do that you need ImpredicativeTypes (which is I believe about to be deprecated). You have to declare Job a data, not a type, and use ExistentialQuantification. 2012/6/13 Ismael Figueroa Palet ifiguer...@gmail.com Do you want to hide the specific types of the job? Presumably to then define a type JobList = [Job] ? You can do that with the ExistentialQuantification extension. type Job = forall k a. Map k a type JobList = [Job] ?? Note you can't unpack the types k a once you have hidden them. But the typechecker can use it to ensure some static property. Also you could use unsafeCoerce to do some casts, but *only if you are *sure* that things will go OK*. 2012/6/13 Magicloud Magiclouds magicloud.magiclo...@gmail.com Hi, I've forgotten this. This is OK: type Job k a = Map k a And this is OK: {-# LANGUAGE RankNTypes #-} -- or LiberalTypeSynonyms? type Job = forall a. forall k. Map k a Then how to write it like this? type Job = Map k a -- 竹密岂妨流水过 山高哪阻野云飞 And for G+, please use magiclouds#gmail.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- Ismael ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What extension do I need to write type Job = Map k a?
Thank you all. I just want to wrap some complex types. So I learn from all info above, I still have to use forall explicitly On Wed, Jun 13, 2012 at 9:19 PM, Yves Parès yves.pa...@gmail.com wrote: Mmmmh... no, to do that you need ImpredicativeTypes (which is I believe about to be deprecated). You have to declare Job a data, not a type, and use ExistentialQuantification. 2012/6/13 Ismael Figueroa Palet ifiguer...@gmail.com Do you want to hide the specific types of the job? Presumably to then define a type JobList = [Job] ? You can do that with the ExistentialQuantification extension. type Job = forall k a. Map k a type JobList = [Job] ?? Note you can't unpack the types k a once you have hidden them. But the typechecker can use it to ensure some static property. Also you could use unsafeCoerce to do some casts, but *only if you are *sure* that things will go OK*. 2012/6/13 Magicloud Magiclouds magicloud.magiclo...@gmail.com Hi, I've forgotten this. This is OK: type Job k a = Map k a And this is OK: {-# LANGUAGE RankNTypes #-} -- or LiberalTypeSynonyms? type Job = forall a. forall k. Map k a Then how to write it like this? type Job = Map k a -- 竹密岂妨流水过 山高哪阻野云飞 And for G+, please use magiclouds#gmail.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- Ismael ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- 竹密岂妨流水过 山高哪阻野云飞 And for G+, please use magiclouds#gmail.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What extension do I need to write type Job = Map k a?
Hi there, Thanks for the reply. To be clear, all I want is to avoid having to type type variables all over the place. What should I do? My original code with RankNTypes and ImpredicativeTypes does not work The type Job = forall k a. M.Map k a works now. But function uses it does not. Compiler complains about Couldn't match expected type `Job' with actual type `M.Map k0 b0'. On Wed, Jun 13, 2012 at 9:15 PM, Daniel Peebles pumpkin...@gmail.com wrote: That doesn't require existential quantification, but it'll need Rank-2 types if you ever do anything with Job. Unfortunately, a universally quantified Job like what you wrote (or what Magicloud seems to want) is only inhabited by the empty Map. An existentially quantified Job, as you might get with data Job = forall k a. Job (Map k a) does let you wrap up any Map containing anything in it, but unfortunately the only thing you can do with that map afterwards is ask for structural properties about it, like whether it's empty or how many elements it has in it. You could ask to enumerate the elements in it, but you wouldn't be able to touch any of them because you wouldn't know what their types were. So I'm not really sure how to interpret the question. Was the goal to have a heterogeneous Map, maybe? Or just to avoid having to type type variables all over the place? Both of those are possible but require a bit more sophistication with types. -Dan On Wed, Jun 13, 2012 at 7:32 AM, Ismael Figueroa Palet ifiguer...@gmail.com wrote: Do you want to hide the specific types of the job? Presumably to then define a type JobList = [Job] ? You can do that with the ExistentialQuantification extension. type Job = forall k a. Map k a type JobList = [Job] ?? Note you can't unpack the types k a once you have hidden them. But the typechecker can use it to ensure some static property. Also you could use unsafeCoerce to do some casts, but *only if you are *sure* that things will go OK*. 2012/6/13 Magicloud Magiclouds magicloud.magiclo...@gmail.com Hi, I've forgotten this. This is OK: type Job k a = Map k a And this is OK: {-# LANGUAGE RankNTypes #-} -- or LiberalTypeSynonyms? type Job = forall a. forall k. Map k a Then how to write it like this? type Job = Map k a -- 竹密岂妨流水过 山高哪阻野云飞 And for G+, please use magiclouds#gmail.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- Ismael ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- 竹密岂妨流水过 山高哪阻野云飞 And for G+, please use magiclouds#gmail.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What extension do I need to write type Job = Map k a?
(resending to café, turns out I wasn't subbed from this address.) Hi Magicloud, This is correct; because you've hidden the type-variables away by universally quantifying them, there's no more level of specificity you can get back *out* of them than just some kind of Map (Job = M.Map k b, where k ≠ k0, b ≠ b0). If you have a Job type which can store *any* kind of Map (forall k a. Job (Map k a)), then that means you could have a Job with a Map Int Bool, and a Job with a Map String (Float - Float), and they'd both have the same type Job. You can't do anything with the values within, because you're being too permissive about what a Job is. You may want data Job k a = Job (Map k a), *or* if you do actually use one kind of Map only, then why not data Job = Job (Map Int String) (substituting your real types for Int and String). In this case, you could also consider using newtype (newtype Job = Job { getJob :: Map Int String }) to provide the guarantee that you're getting a Job (and not any Map Int String) without performance loss. Let me know if I've been more confusing than helpful; Arlen On Thursday, 14 June 2012 at 1:16 PM, Magicloud Magiclouds wrote: Hi there, Thanks for the reply. To be clear, all I want is to avoid having to type type variables all over the place. What should I do? My original code with RankNTypes and ImpredicativeTypes does not work The type Job = forall k a. M.Map k a works now. But function uses it does not. Compiler complains about Couldn't match expected type `Job' with actual type `M.Map k0 b0'. On Wed, Jun 13, 2012 at 9:15 PM, Daniel Peebles pumpkin...@gmail.com (mailto:pumpkin...@gmail.com) wrote: That doesn't require existential quantification, but it'll need Rank-2 typesif you ever do anything with Job. Unfortunately, a universally quantifiedJob like what you wrote (or what Magicloud seems to want) is only inhabitedby the empty Map. An existentially quantified Job, as you might get with data Job = forall k a. Job (Map k a) does let you wrap up any Map containing anything in it, but unfortunatelythe only thing you can do with that map afterwards is ask for structuralproperties about it, like whether it's empty or how many elements it has init. You could ask to enumerate the elements in it, but you wouldn't be ableto touch any of them because you wouldn't know what their types were. So I'm not really sure how to interpret the question. Was the goal to have aheterogeneous Map, maybe? Or just to avoid having to type type variables allover the place? Both of those are possible but require a bit moresophistication with types. -Dan On Wed, Jun 13, 2012 at 7:32 AM, Ismael Figueroa Paletifiguer...@gmail.com (mailto:ifiguer...@gmail.com) wrote: Do you want to hide the specific types of the job? Presumably to thendefine a type JobList = [Job] ?You can do that with the ExistentialQuantification extension. type Job = forall k a. Map k atype JobList = [Job] ??Note you can't unpack the types k a once you have hidden them. But thetypechecker can use it to ensure some static property.Also you could use unsafeCoerce to do some casts, but *only if you are*sure* that things will go OK*. 2012/6/13 Magicloud Magiclouds magicloud.magiclo...@gmail.com (mailto:magicloud.magiclo...@gmail.com) Hi,I've forgotten this.This is OK:type Job k a = Map k aAnd this is OK:{-# LANGUAGE RankNTypes #-} -- or LiberalTypeSynonyms?type Job = forall a. forall k. Map k a Then how to write it like this?type Job = Map k a--竹密岂妨流水过山高哪阻野云飞 And for G+, please use magiclouds#gmail.com (http://gmail.com). ___Haskell-Cafe mailing listhaskell-c...@haskell.org (mailto:Haskell-Cafe@haskell.org) http://www.haskell.org/mailman/listinfo/haskell-cafe --Ismael ___Haskell-Cafe mailing listhaskell-c...@haskell.org (mailto:Haskell-Cafe@haskell.org) http://www.haskell.org/mailman/listinfo/haskell-cafe -- 竹密岂妨流水过 山高哪阻野云飞 And for G+, please use magiclouds#gmail.com (http://gmail.com). ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org (mailto:Haskell-Cafe@haskell.org) http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What extension do I need to write type Job = Map k a?
OK. I think I understand a little. I use Job here just wants to simplify the code. And since I provide the function as library, I cannot decide what exact type k is. What should I do? On Thu, Jun 14, 2012 at 11:23 AM, Arlen Cuss a...@len.me wrote: (resending to café, turns out I wasn't subbed from this address.) Hi Magicloud, This is correct; because you've hidden the type-variables away by universally quantifying them, there's no more level of specificity you can get back *out* of them than just some kind of Map (Job = M.Map k b, where k ≠ k0, b ≠ b0). If you have a Job type which can store *any* kind of Map (forall k a. Job (Map k a)), then that means you could have a Job with a Map Int Bool, and a Job with a Map String (Float - Float), and they'd both have the same type Job. You can't do anything with the values within, because you're being too permissive about what a Job is. You may want data Job k a = Job (Map k a), *or* if you do actually use one kind of Map only, then why not data Job = Job (Map Int String) (substituting your real types for Int and String). In this case, you could also consider using newtype (newtype Job = Job { getJob :: Map Int String }) to provide the guarantee that you're getting a Job (and not any Map Int String) without performance loss. Let me know if I've been more confusing than helpful; Arlen On Thursday, 14 June 2012 at 1:16 PM, Magicloud Magiclouds wrote: Hi there, Thanks for the reply. To be clear, all I want is to avoid having to type type variables all over the place. What should I do? My original code with RankNTypes and ImpredicativeTypes does not work The type Job = forall k a. M.Map k a works now. But function uses it does not. Compiler complains about Couldn't match expected type `Job' with actual type `M.Map k0 b0'. On Wed, Jun 13, 2012 at 9:15 PM, Daniel Peebles pumpkin...@gmail.com (mailto:pumpkin...@gmail.com) wrote: That doesn't require existential quantification, but it'll need Rank-2 typesif you ever do anything with Job. Unfortunately, a universally quantifiedJob like what you wrote (or what Magicloud seems to want) is only inhabitedby the empty Map. An existentially quantified Job, as you might get with data Job = forall k a. Job (Map k a) does let you wrap up any Map containing anything in it, but unfortunatelythe only thing you can do with that map afterwards is ask for structuralproperties about it, like whether it's empty or how many elements it has init. You could ask to enumerate the elements in it, but you wouldn't be ableto touch any of them because you wouldn't know what their types were. So I'm not really sure how to interpret the question. Was the goal to have aheterogeneous Map, maybe? Or just to avoid having to type type variables allover the place? Both of those are possible but require a bit moresophistication with types. -Dan On Wed, Jun 13, 2012 at 7:32 AM, Ismael Figueroa Paletifiguer...@gmail.com (mailto:ifiguer...@gmail.com) wrote: Do you want to hide the specific types of the job? Presumably to thendefine a type JobList = [Job] ?You can do that with the ExistentialQuantification extension. type Job = forall k a. Map k atype JobList = [Job] ??Note you can't unpack the types k a once you have hidden them. But thetypechecker can use it to ensure some static property.Also you could use unsafeCoerce to do some casts, but *only if you are*sure* that things will go OK*. 2012/6/13 Magicloud Magiclouds magicloud.magiclo...@gmail.com (mailto:magicloud.magiclo...@gmail.com) Hi,I've forgotten this.This is OK:type Job k a = Map k aAnd this is OK:{-# LANGUAGE RankNTypes #-} -- or LiberalTypeSynonyms?type Job = forall a. forall k. Map k a Then how to write it like this?type Job = Map k a--竹密岂妨流水过山高哪阻野云飞 And for G+, please use magiclouds#gmail.com (http://gmail.com). ___Haskell-Cafe mailing listhaskell-c...@haskell.org (mailto:Haskell-Cafe@haskell.org) http://www.haskell.org/mailman/listinfo/haskell-cafe --Ismael ___Haskell-Cafe mailing listhaskell-c...@haskell.org (mailto:Haskell-Cafe@haskell.org) http://www.haskell.org/mailman/listinfo/haskell-cafe -- 竹密岂妨流水过 山高哪阻野云飞 And for G+, please use magiclouds#gmail.com (http://gmail.com). ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org (mailto: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 -- 竹密岂妨流水过 山高哪阻野云飞 And for G+, please use magiclouds#gmail.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org
Re: [Haskell-cafe] What extension do I need to write type Job = Map k a?
On 14 June 2012 14:20, Magicloud Magiclouds magicloud.magiclo...@gmail.com wrote: OK. I think I understand a little. I use Job here just wants to simplify the code. And since I provide the function as library, I cannot decide what exact type k is. What should I do? Do you know what the type of `a'? If so: type Job k = Map k String Otherwise... do you even need a type alias? On Thu, Jun 14, 2012 at 11:23 AM, Arlen Cuss a...@len.me wrote: (resending to café, turns out I wasn't subbed from this address.) Hi Magicloud, This is correct; because you've hidden the type-variables away by universally quantifying them, there's no more level of specificity you can get back *out* of them than just some kind of Map (Job = M.Map k b, where k ≠ k0, b ≠ b0). If you have a Job type which can store *any* kind of Map (forall k a. Job (Map k a)), then that means you could have a Job with a Map Int Bool, and a Job with a Map String (Float - Float), and they'd both have the same type Job. You can't do anything with the values within, because you're being too permissive about what a Job is. You may want data Job k a = Job (Map k a), *or* if you do actually use one kind of Map only, then why not data Job = Job (Map Int String) (substituting your real types for Int and String). In this case, you could also consider using newtype (newtype Job = Job { getJob :: Map Int String }) to provide the guarantee that you're getting a Job (and not any Map Int String) without performance loss. Let me know if I've been more confusing than helpful; Arlen On Thursday, 14 June 2012 at 1:16 PM, Magicloud Magiclouds wrote: Hi there, Thanks for the reply. To be clear, all I want is to avoid having to type type variables all over the place. What should I do? My original code with RankNTypes and ImpredicativeTypes does not work The type Job = forall k a. M.Map k a works now. But function uses it does not. Compiler complains about Couldn't match expected type `Job' with actual type `M.Map k0 b0'. On Wed, Jun 13, 2012 at 9:15 PM, Daniel Peebles pumpkin...@gmail.com (mailto:pumpkin...@gmail.com) wrote: That doesn't require existential quantification, but it'll need Rank-2 typesif you ever do anything with Job. Unfortunately, a universally quantifiedJob like what you wrote (or what Magicloud seems to want) is only inhabitedby the empty Map. An existentially quantified Job, as you might get with data Job = forall k a. Job (Map k a) does let you wrap up any Map containing anything in it, but unfortunatelythe only thing you can do with that map afterwards is ask for structuralproperties about it, like whether it's empty or how many elements it has init. You could ask to enumerate the elements in it, but you wouldn't be ableto touch any of them because you wouldn't know what their types were. So I'm not really sure how to interpret the question. Was the goal to have aheterogeneous Map, maybe? Or just to avoid having to type type variables allover the place? Both of those are possible but require a bit moresophistication with types. -Dan On Wed, Jun 13, 2012 at 7:32 AM, Ismael Figueroa Paletifiguer...@gmail.com (mailto:ifiguer...@gmail.com) wrote: Do you want to hide the specific types of the job? Presumably to thendefine a type JobList = [Job] ?You can do that with the ExistentialQuantification extension. type Job = forall k a. Map k atype JobList = [Job] ??Note you can't unpack the types k a once you have hidden them. But thetypechecker can use it to ensure some static property.Also you could use unsafeCoerce to do some casts, but *only if you are*sure* that things will go OK*. 2012/6/13 Magicloud Magiclouds magicloud.magiclo...@gmail.com (mailto:magicloud.magiclo...@gmail.com) Hi,I've forgotten this.This is OK:type Job k a = Map k aAnd this is OK:{-# LANGUAGE RankNTypes #-} -- or LiberalTypeSynonyms?type Job = forall a. forall k. Map k a Then how to write it like this?type Job = Map k a--竹密岂妨流水过山高哪阻野云飞 And for G+, please use magiclouds#gmail.com (http://gmail.com). ___Haskell-Cafe mailing listhaskell-c...@haskell.org (mailto:Haskell-Cafe@haskell.org) http://www.haskell.org/mailman/listinfo/haskell-cafe --Ismael ___Haskell-Cafe mailing listhaskell-c...@haskell.org (mailto:Haskell-Cafe@haskell.org) http://www.haskell.org/mailman/listinfo/haskell-cafe -- 竹密岂妨流水过 山高哪阻野云飞 And for G+, please use magiclouds#gmail.com (http://gmail.com). ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org (mailto:Haskell-Cafe@haskell.org) http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org