From silent.leaf0 at gmail.com Sat Jul 1 13:09:31 2017 From: silent.leaf0 at gmail.com (Silent Leaf) Date: Sat, 1 Jul 2017 15:09:31 +0200 Subject: [Haskell-beginners] pure instead of return? Message-ID: hi, i just wanted to know, if i use pure instead of return, if there's any single risk of getting a different implementation of the function, or anything of that kind. also, am i right to assume that GHC will do what is needed so there's no actual redirection in the compiled code, in the case pure is defined in terms of return? thanks -------------- next part -------------- An HTML attachment was scrubbed... URL: From silent.leaf0 at gmail.com Sat Jul 1 17:47:57 2017 From: silent.leaf0 at gmail.com (Silent Leaf) Date: Sat, 1 Jul 2017 19:47:57 +0200 Subject: [Haskell-beginners] pure instead of return? In-Reply-To: References: Message-ID: btw: does the name of "pure" come from the idea that the monad IO is "impure" (which does not seem to be the case, does it?) or is it more of a mathematical concept of pure values vs values whose types are functors/applicatives/monads? or is it a way to say "simplest way to wrap the value, purest (least "modified") equivalent of the value as wrapped value"? 2017-07-01 15:09 GMT+02:00 Silent Leaf : > hi, > > i just wanted to know, if i use pure instead of return, if there's any > single risk of getting a different implementation of the function, or > anything of that kind. also, am i right to assume that GHC will do what is > needed so there's no actual redirection in the compiled code, in the case > pure is defined in terms of return? > > thanks > -------------- next part -------------- An HTML attachment was scrubbed... URL: From fa-ml at ariis.it Sat Jul 1 18:03:30 2017 From: fa-ml at ariis.it (Francesco Ariis) Date: Sat, 1 Jul 2017 20:03:30 +0200 Subject: [Haskell-beginners] pure instead of return? In-Reply-To: References: Message-ID: <20170701180330.GA21551@x60s.casa> On Sat, Jul 01, 2017 at 07:47:57PM +0200, Silent Leaf wrote: > [..] or is it a way to say "simplest way to wrap > the value, purest (least "modified") equivalent of the value as wrapped > value"? ^-- this one. `pure` and `return` are synonyms. There are two words for the same concept for historical reasons. Using pure does not incurs in monad constraints, so if you can you might want to use that. From silent.leaf0 at gmail.com Sat Jul 1 18:18:57 2017 From: silent.leaf0 at gmail.com (Silent Leaf) Date: Sat, 1 Jul 2017 20:18:57 +0200 Subject: [Haskell-beginners] pure instead of return? In-Reply-To: <20170701180330.GA21551@x60s.casa> References: <20170701180330.GA21551@x60s.casa> Message-ID: but i can use pure every time return is usable, can i not? every applicatives are monads right? i don't get the "if you can" part. why could i not? 2017-07-01 20:03 GMT+02:00 Francesco Ariis : > On Sat, Jul 01, 2017 at 07:47:57PM +0200, Silent Leaf wrote: > > [..] or is it a way to say "simplest way to wrap > > the value, purest (least "modified") equivalent of the value as wrapped > > value"? > > ^-- this one. > > `pure` and `return` are synonyms. There are two words for the same concept > for historical reasons. Using pure does not incurs in monad constraints, > so if you can you might want to use that. > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: From steffenomak at gmail.com Sat Jul 1 19:46:45 2017 From: steffenomak at gmail.com (Stefan Risberg) Date: Sat, 1 Jul 2017 21:46:45 +0200 Subject: [Haskell-beginners] pure instead of return? In-Reply-To: References: <20170701180330.GA21551@x60s.casa> Message-ID: Every monad is applicative, but every instance of applicative does not have a monad one On 1 Jul. 2017 20:19, "Silent Leaf" wrote: > but i can use pure every time return is usable, can i not? every > applicatives are monads right? i don't get the "if you can" part. why could > i not? > > 2017-07-01 20:03 GMT+02:00 Francesco Ariis : > >> On Sat, Jul 01, 2017 at 07:47:57PM +0200, Silent Leaf wrote: >> > [..] or is it a way to say "simplest way to wrap >> > the value, purest (least "modified") equivalent of the value as wrapped >> > value"? >> >> ^-- this one. >> >> `pure` and `return` are synonyms. There are two words for the same concept >> for historical reasons. Using pure does not incurs in monad constraints, >> so if you can you might want to use that. >> _______________________________________________ >> Beginners mailing list >> Beginners at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners >> > > > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From silent.leaf0 at gmail.com Sat Jul 1 19:54:17 2017 From: silent.leaf0 at gmail.com (Silent Leaf) Date: Sat, 1 Jul 2017 21:54:17 +0200 Subject: [Haskell-beginners] pure instead of return? In-Reply-To: References: <20170701180330.GA21551@x60s.casa> Message-ID: yeah i know, so why did you say "so if you can you might want to use that"? 2017-07-01 21:46 GMT+02:00 Stefan Risberg : > Every monad is applicative, but every instance of applicative does not > have a monad one > > On 1 Jul. 2017 20:19, "Silent Leaf" wrote: > >> but i can use pure every time return is usable, can i not? every >> applicatives are monads right? i don't get the "if you can" part. why could >> i not? >> >> 2017-07-01 20:03 GMT+02:00 Francesco Ariis : >> >>> On Sat, Jul 01, 2017 at 07:47:57PM +0200, Silent Leaf wrote: >>> > [..] or is it a way to say "simplest way to wrap >>> > the value, purest (least "modified") equivalent of the value as wrapped >>> > value"? >>> >>> ^-- this one. >>> >>> `pure` and `return` are synonyms. There are two words for the same >>> concept >>> for historical reasons. Using pure does not incurs in monad constraints, >>> so if you can you might want to use that. >>> _______________________________________________ >>> Beginners mailing list >>> Beginners at haskell.org >>> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners >>> >> >> >> _______________________________________________ >> Beginners mailing list >> Beginners at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners >> >> > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From fa-ml at ariis.it Sat Jul 1 20:03:35 2017 From: fa-ml at ariis.it (Francesco Ariis) Date: Sat, 1 Jul 2017 22:03:35 +0200 Subject: [Haskell-beginners] pure instead of return? In-Reply-To: References: <20170701180330.GA21551@x60s.casa> Message-ID: <20170701200335.GA26139@x60s.casa> On Sat, Jul 01, 2017 at 08:18:57PM +0200, Silent Leaf wrote: > but i can use pure every time return is usable, can i not? every > applicatives are monads right? i don't get the "if you can" part. why could > i not? Say I am contributing to a project, and they use `return`, I am not going die on the `pure` hill, you just go with what the style is. From silent.leaf0 at gmail.com Sun Jul 2 12:00:16 2017 From: silent.leaf0 at gmail.com (Silent Leaf) Date: Sun, 2 Jul 2017 14:00:16 +0200 Subject: [Haskell-beginners] pure instead of return? In-Reply-To: <20170701200335.GA26139@x60s.casa> References: <20170701180330.GA21551@x60s.casa> <20170701200335.GA26139@x60s.casa> Message-ID: ok, got it; yes you're right. though mind you it's so barely used i'm not sure it'd really break the style that much. but depends on whoever else is in the boat. 2017-07-01 22:03 GMT+02:00 Francesco Ariis : > On Sat, Jul 01, 2017 at 08:18:57PM +0200, Silent Leaf wrote: > > but i can use pure every time return is usable, can i not? every > > applicatives are monads right? i don't get the "if you can" part. why > could > > i not? > > Say I am contributing to a project, and they use `return`, I am not going > die on the `pure` hill, you just go with what the style is. > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: From saikyun at gmail.com Tue Jul 4 10:06:39 2017 From: saikyun at gmail.com (Jona Ekenberg) Date: Tue, 4 Jul 2017 12:06:39 +0200 Subject: [Haskell-beginners] Reversing a list Message-ID: Hello, I'm currently going through the exercises in chapter 3 of Real World Haskell. One of the exercises challenges me to create a function which takes a list and makes a palindrome of it. I tried to solve it this way: palindrome :: [t] -> [t] palindrome xs = xs ++ (reverse xs) where reverse [] = [] reverse (x:xs) = (reverse xs) ++ x But when I try to compile this I get this error: Kapitel3.hs:14:32-33: error: … • Couldn't match type ‘t’ with ‘[t]’ ‘t’ is a rigid type variable bound by the type signature for: palindrome :: forall t. [t] -> [t] at /Users/jona/programmering/haskell/boken/Kapitel3.hs:13:15 Expected type: [[t]] Actual type: [t] • In the first argument of ‘reverse’, namely ‘xs’ In the second argument of ‘(++)’, namely ‘(reverse xs)’ In the expression: xs ++ (reverse xs) • Relevant bindings include xs :: [t] (bound at /Users/jona/programmering/haskell/boken/Kapitel3.hs:14:12) palindrome :: [t] -> [t] (bound at /Users/jona/programmering/haskell/boken/Kapitel3.hs:14:1) Compilation failed. It looks like I have used a function that want a list of lists, but I don't understand where. Also, is there some way to declare the type of my reverse-function in this case? Kind regards, Jona Ekenberg -------------- next part -------------- An HTML attachment was scrubbed... URL: From frederic.cogny at gmail.com Tue Jul 4 10:17:43 2017 From: frederic.cogny at gmail.com (Frederic Cogny) Date: Tue, 04 Jul 2017 10:17:43 +0000 Subject: [Haskell-beginners] Reversing a list In-Reply-To: References: Message-ID: Looks like you're missing the square brackets around your x in the definition of reverse (the ++ takes two lists, hence the error message) Try this palindrome :: [t] -> [t] palindrome xs = xs ++ (reverse xs) where reverse [] = [] reverse (x:xs) = (reverse xs) ++ *[*x*]* to declare the type you can define it outside or annotate it within you're code palindrome :: [t] -> [t] palindrome xs = xs ++ (reverse xs) where * reverse :: [t] -> [t]* reverse [] = [] reverse (x:xs) = (reverse xs) ++ *[*x*]* On Tue, Jul 4, 2017 at 12:07 PM Jona Ekenberg wrote: > Hello, > > I'm currently going through the exercises in chapter 3 of Real World > Haskell. One of the exercises challenges me to create a function which > takes a list and makes a palindrome of it. > > I tried to solve it this way: > palindrome :: [t] -> [t] > palindrome xs = xs ++ (reverse xs) > where > reverse [] = [] > reverse (x:xs) = (reverse xs) ++ x > > But when I try to compile this I get this error: > Kapitel3.hs:14:32-33: error: … > • Couldn't match type ‘t’ with ‘[t]’ > ‘t’ is a rigid type variable bound by > the type signature for: > palindrome :: forall t. [t] -> [t] > at /Users/jona/programmering/haskell/boken/Kapitel3.hs:13:15 > Expected type: [[t]] > Actual type: [t] > • In the first argument of ‘reverse’, namely ‘xs’ > In the second argument of ‘(++)’, namely ‘(reverse xs)’ > In the expression: xs ++ (reverse xs) > • Relevant bindings include > xs :: [t] > (bound at > /Users/jona/programmering/haskell/boken/Kapitel3.hs:14:12) > palindrome :: [t] -> [t] > (bound at > /Users/jona/programmering/haskell/boken/Kapitel3.hs:14:1) > Compilation failed. > > It looks like I have used a function that want a list of lists, but I > don't understand where. > Also, is there some way to declare the type of my reverse-function in this > case? > > Kind regards, > Jona Ekenberg > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > -- Frederic Cogny +33 7 83 12 61 69 -------------- next part -------------- An HTML attachment was scrubbed... URL: From fa-ml at ariis.it Tue Jul 4 10:20:36 2017 From: fa-ml at ariis.it (Francesco Ariis) Date: Tue, 4 Jul 2017 12:20:36 +0200 Subject: [Haskell-beginners] Reversing a list In-Reply-To: References: Message-ID: <20170704102036.pbcapqdfwjmpjfcn@x60s.casa> On Tue, Jul 04, 2017 at 12:06:39PM +0200, Jona Ekenberg wrote: > Hello, > > I'm currently going through the exercises in chapter 3 of Real World > Haskell. One of the exercises challenges me to create a function which > takes a list and makes a palindrome of it. > > I tried to solve it this way: > palindrome :: [t] -> [t] > palindrome xs = xs ++ (reverse xs) > where > reverse [] = [] > reverse (x:xs) = (reverse xs) ++ x Hello Jona, let's analyse the error. It points to this bit: palindrome xs = xs ++ (reverse xs) And it says: I expected [[t]], but you gave me [t]. Whenever I encounter such an error I try to write explicit type signatures so to make diagnosing easier. In your example palindrome :: [t] -> [t] palindrome xs = xs ++ (reverse xs) where reverse :: [t] -> [t] -- explicit type signature reverse [] = [] reverse (x:xs) = (reverse xs) ++ x If we :reload ghci complains again, the offending bit being reverse (x:xs) = (reverse xs) ++ x ^ Expected type is [t1] but we passed t. Not it is clear! The type of `++` is: λ> :t (++) (++) :: [a] -> [a] -> [a] and `x` is a single element. When we replace `x` with `[x]` everything works. Does that help? -F P.S.: Real World Haskell is an excellent book but sometimes can be a tad difficult to follow. If you want to integrate with another source, CIS194 [1] is an excellent choice: free, thorough, full of home-works and interactive. [1] http://www.cis.upenn.edu/~cis194/fall16/ From saikyun at gmail.com Tue Jul 4 10:26:53 2017 From: saikyun at gmail.com (Jona Ekenberg) Date: Tue, 4 Jul 2017 12:26:53 +0200 Subject: [Haskell-beginners] Reversing a list In-Reply-To: <20170704102036.pbcapqdfwjmpjfcn@x60s.casa> References: <20170704102036.pbcapqdfwjmpjfcn@x60s.casa> Message-ID: Thank you both for your answers, I somehow thought ++ acted as both append and concat, since I've mostly used it on strings where I haven't had to think about it. And thank you for the tips regarding adding explicit types and the reading material. So far I feel that I'm able to follow along quite well, but it's nice to have a second source! Grateful regards, Jona Den 4 juli 2017 12:21 em skrev "Francesco Ariis" : On Tue, Jul 04, 2017 at 12:06:39PM +0200, Jona Ekenberg wrote: > Hello, > > I'm currently going through the exercises in chapter 3 of Real World > Haskell. One of the exercises challenges me to create a function which > takes a list and makes a palindrome of it. > > I tried to solve it this way: > palindrome :: [t] -> [t] > palindrome xs = xs ++ (reverse xs) > where > reverse [] = [] > reverse (x:xs) = (reverse xs) ++ x Hello Jona, let's analyse the error. It points to this bit: palindrome xs = xs ++ (reverse xs) And it says: I expected [[t]], but you gave me [t]. Whenever I encounter such an error I try to write explicit type signatures so to make diagnosing easier. In your example palindrome :: [t] -> [t] palindrome xs = xs ++ (reverse xs) where reverse :: [t] -> [t] -- explicit type signature reverse [] = [] reverse (x:xs) = (reverse xs) ++ x If we :reload ghci complains again, the offending bit being reverse (x:xs) = (reverse xs) ++ x ^ Expected type is [t1] but we passed t. Not it is clear! The type of `++` is: λ> :t (++) (++) :: [a] -> [a] -> [a] and `x` is a single element. When we replace `x` with `[x]` everything works. Does that help? -F P.S.: Real World Haskell is an excellent book but sometimes can be a tad difficult to follow. If you want to integrate with another source, CIS194 [1] is an excellent choice: free, thorough, full of home-works and interactive. [1] http://www.cis.upenn.edu/~cis194/fall16/ _______________________________________________ Beginners mailing list Beginners at haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners -------------- next part -------------- An HTML attachment was scrubbed... URL: From raabe at froglogic.com Tue Jul 4 10:36:28 2017 From: raabe at froglogic.com (Frerich Raabe) Date: Tue, 04 Jul 2017 12:36:28 +0200 Subject: [Haskell-beginners] Reversing a list In-Reply-To: References: Message-ID: <019d562d269c99c6650a1b5b839d3bc1@froglogic.com> On 2017-07-04 12:06, Jona Ekenberg wrote: > Hello, > > I'm currently going through the exercises in chapter 3 of Real World > Haskell. One of the exercises challenges me to create a function which > takes a list and makes a palindrome of it. > > I tried to solve it this way: > > palindrome :: [t] -> [t] > palindrome xs = xs ++ (reverse xs) > where > reverse [] = [] > reverse (x:xs) = (reverse xs) ++ x > > But when I try to compile this I get this error: [..] This is caused by Haskell trying hard to make your code type check but the noticing that it just cannot make the parts fit together. I suspect the cause of this is the definition reverse (x:xs) = (reverse xs) ++ x What's noteworthy about this is: 1. The type of the ':' constructor you used in the pattern match is 'a -> [a] -> [a]', i.e. the first argument is of some type 'a' (in Haskell nomenclature, 'x :: a') and the second argument is a list (i.e. 'xs :: [a]'). So your compiler knows that no matter what type 'x' is, 'xs' will be a list of those things. 2. The type of the '++' function you used on the right-hand side is '[a] -> [a] -> [a]', i.e. the first and the second argument must be of the same type (a list of things). Since the second argument must be a list, this means that 'x' must be a list and hence (considering 1. above) 'xs' must be a list of lists. This means that your 'reverse' definition must be of type '[[a]] -> [a]': it takes a list of list of things and yields a list of things. I.e. it takes and returns different type sof things. This however is in conflict with your first definition: palindrome xs = xs ⧺ (reverse xs) For 'xs ⧺ (reverse xs)' to be sound (to 'type-check'), the expressions 'xs' and '(reverse xs)' have to be of the same type. And since 'xs' is also an argument to 'reverse' it means that 'reverse' has to take and yield values of the same type. You can resolve this conflict by changing reverse (x:xs) = (reverse xs) ++ x to reverse (x:xs) = (reverse xs) ++ [x] -- Frerich Raabe - raabe at froglogic.com www.froglogic.com - Multi-Platform GUI Testing From aquagnu at gmail.com Thu Jul 6 08:12:55 2017 From: aquagnu at gmail.com (Baa) Date: Thu, 6 Jul 2017 11:12:55 +0300 Subject: [Haskell-beginners] Get rid of Maybes in complex types Message-ID: <20170706111255.1d6695b8@Pavel> Hello Dear List! Consider, I retrieve from external source some data. Internally it's represented as some complex type with `Maybe` fields, even more, some of fields are record types and have `Maybe` fields too. They are Maybe's because some information in this data can be missing (user error or it not very valuable and can be skipped): data A = A { a1 :: Maybe B ... } data B = B { b1 :: Maybe C ... } I retrieve it from network, files, i.e. external world, then I validate it, report errors of some missing fields, fix another one (which can be fixed, for example, replace Nothing with `Just default_value` or even I can fix `Just wrong` to `Just right`, etc, etc). After all of this, I know that I have "clean" data, so all my complex types now have `Just right_value` fields. But I need to process them as optional, with possible Nothing case! To avoid it I must create copies of `A`, `B`, etc, where `a1`, `b1` will be `B`, `C`, not `Maybe B`, `Maybe C`. Sure, it's not a case. After processing and filtering, I create, for example, some resulting objects: data Result { a :: A -- not Maybe! ... } And even more: `a::A` in `Result` (I know it, after filtering) will not contain Nothings, only `Just right_values`s. But each function which consumes `A` must do something with possible Nothing values even after filtering and fixing of `A`s. I have, for example, function: createResults :: [A] -> [Result] createResults alst = ... case of (a1 theA) -> Just right_value -> ... Nothing -> logError undefined -- can not happen Fun here is: that it happens (I found bug in my filtering code with this `undefined`). But now I thought about it: what is the idiomatic way to solve such situation? When you need to have: - COMPLEX type WITH Maybes - the same type WITHOUT Maybes Alternative is to keep this Maybes to the very end of processing, what I don't like. Or to have types copies, which is more terrible, sure. PS. I threw IOs away to show only the crux of the problem. --- Cheers, Paul From imantc at gmail.com Thu Jul 6 08:24:39 2017 From: imantc at gmail.com (Imants Cekusins) Date: Thu, 6 Jul 2017 11:24:39 +0300 Subject: [Haskell-beginners] Get rid of Maybes in complex types In-Reply-To: <20170706111255.1d6695b8@Pavel> References: <20170706111255.1d6695b8@Pavel> Message-ID: Identity http://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Identity.html may work: data A m = A { a1 :: m B } data B m = B { b1 :: m C ... } m: Maybe or Identity - any good? On 6 July 2017 at 11:12, Baa wrote: > Hello Dear List! > > Consider, I retrieve from external source some data. Internally it's > represented as some complex type with `Maybe` fields, even more, some > of fields are record types and have `Maybe` fields too. They are > Maybe's because some information in this data can be missing (user > error or it not very valuable and can be skipped): > > data A = A { > a1 :: Maybe B > ... } > data B = B { > b1 :: Maybe C > ... } > > I retrieve it from network, files, i.e. external world, then I validate > it, report errors of some missing fields, fix another one (which can be > fixed, for example, replace Nothing with `Just default_value` or even I > can fix `Just wrong` to `Just right`, etc, etc). After all of this, I > know that I have "clean" data, so all my complex types now have `Just > right_value` fields. But I need to process them as optional, with > possible Nothing case! To avoid it I must create copies of `A`, `B`, > etc, where `a1`, `b1` will be `B`, `C`, not `Maybe B`, `Maybe C`. Sure, > it's not a case. > > After processing and filtering, I create, for example, some resulting > objects: > > data Result { > a :: A -- not Maybe! > ... } > > And even more: `a::A` in `Result` (I know it, after filtering) will not > contain Nothings, only `Just right_values`s. > > But each function which consumes `A` must do something with possible > Nothing values even after filtering and fixing of `A`s. > > I have, for example, function: > > createResults :: [A] -> [Result] > createResults alst = > ... > case of (a1 theA) -> > Just right_value -> ... > Nothing -> > logError > undefined -- can not happen > > Fun here is: that it happens (I found bug in my filtering > code with this `undefined`). But now I thought about it: what is the > idiomatic way to solve such situation? When you need to have: > > - COMPLEX type WITH Maybes > - the same type WITHOUT Maybes > > Alternative is to keep this Maybes to the very end of processing, what I > don't like. Or to have types copies, which is more terrible, sure. > > PS. I threw IOs away to show only the crux of the problem. > > --- > Cheers, > Paul > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: From saikyun at gmail.com Thu Jul 6 09:12:04 2017 From: saikyun at gmail.com (Jona Ekenberg) Date: Thu, 6 Jul 2017 11:12:04 +0200 Subject: [Haskell-beginners] Incomplete patterns Message-ID: Hello, I am currently going through the CIS194 spring 13 course, since it has been recommended by several haskellions. I find the exercises extremely valuable, and the reading material is succinct (in a good way). I just finished the exercises for lesson two, and while everything works, I get this warning: Lektion02.hs:(38,1)-(44,21): warning: [-Wincomplete-patterns] … Pattern match(es) are non-exhaustive In an equation for ‘insert’: Patterns not matched: (LogMessage _ _ _) (Node _ (LogMessage _ _ _) _) I understand that there is a pattern I'm not covering, but I can't really figure out which one. Here is my function: insert :: LogMessage -> MessageTree -> MessageTree insert (Unknown _) mt = mt insert m Leaf = Node Leaf m Leaf insert m@(LogMessage _ t _) (Node left value@(LogMessage _ t' _) right) | t <= t' = Node (insert m left) value right | t > t' = Node left value (insert m right) insert m@(LogMessage _ _ _) (Node left (Unknown _) right) = Node left m right (here's a pastebin with intact indentation: http://lpaste.net/356716) I am not sure on how I should progress to find out which pattern I'm missing. Any help is appreciated. Kind regards, Jona -------------- next part -------------- An HTML attachment was scrubbed... URL: From sylvain at haskus.fr Thu Jul 6 09:21:35 2017 From: sylvain at haskus.fr (Sylvain Henry) Date: Thu, 6 Jul 2017 11:21:35 +0200 Subject: [Haskell-beginners] Incomplete patterns In-Reply-To: References: Message-ID: <203988f4-5c4c-e7f1-5d5a-ed5555ec52bb@haskus.fr> Hi, In the following code: insert m@(LogMessage _ t _) (Node left value@(LogMessage _ t' _) right) | t <= t' = Node (insert m left) value right | t > t' = Node left value (insert m right) GHC can't detect that both guards (t <= t') and (t > t') cover all cases. The usual way to deal with this is to use "otherwise" (which is always true): insert m@(LogMessage _ t _) (Node left value@(LogMessage _ t' _) right) | t <= t' = Node (insert m left) value right | otherwise = Node left value (insert m right) Regards, Sylvain On 06/07/2017 11:12, Jona Ekenberg wrote: > Hello, > > I am currently going through the CIS194 spring 13 course, since it has > been recommended by several haskellions. I find the exercises > extremely valuable, and the reading material is succinct (in a good way). > > I just finished the exercises for lesson two, and while everything > works, I get this warning: > Lektion02.hs:(38,1)-(44,21): warning: [-Wincomplete-patterns] … > Pattern match(es) are non-exhaustive > In an equation for ‘insert’: > Patterns not matched: > (LogMessage _ _ _) (Node _ (LogMessage _ _ _) _) > > I understand that there is a pattern I'm not covering, but I can't > really figure out which one. Here is my function: > insert :: LogMessage -> MessageTree -> MessageTree > insert (Unknown _) mt = mt > insert m Leaf = Node Leaf m Leaf > insert m@(LogMessage _ t _) (Node left value@(LogMessage _ t' _) right) > | t <= t' = Node (insert m left) value right > | t > t' = Node left value (insert m right) > insert m@(LogMessage _ _ _) (Node left (Unknown _) right) > = Node left m right > > (here's a pastebin with intact indentation: http://lpaste.net/356716) > > I am not sure on how I should progress to find out which pattern I'm > missing. > Any help is appreciated. > > Kind regards, > Jona > > > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners -------------- next part -------------- An HTML attachment was scrubbed... URL: From aquagnu at gmail.com Thu Jul 6 10:01:05 2017 From: aquagnu at gmail.com (Baa) Date: Thu, 6 Jul 2017 13:01:05 +0300 Subject: [Haskell-beginners] Get rid of Maybes in complex types In-Reply-To: References: <20170706111255.1d6695b8@Pavel> Message-ID: <20170706130105.4112f723@Pavel> But will it work if I switch from one monad to another? Actually, I have something like piping/conduit, and if I switch items in pipe from `A Maybe` to `A Idenitity` - will it work? Whether it will be compiled? Although I certainly can "map" items from one type to another... Idea looks interesting sure :) > Identity > > http://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Identity.html > > may work: > > data A m = A { > a1 :: m B > } > data B m = B { > b1 :: m C > ... } > > m: Maybe or Identity > > - any good? > > > > On 6 July 2017 at 11:12, Baa wrote: > > > Hello Dear List! > > > > Consider, I retrieve from external source some data. Internally it's > > represented as some complex type with `Maybe` fields, even more, > > some of fields are record types and have `Maybe` fields too. They > > are Maybe's because some information in this data can be missing > > (user error or it not very valuable and can be skipped): > > > > data A = A { > > a1 :: Maybe B > > ... } > > data B = B { > > b1 :: Maybe C > > ... } > > > > I retrieve it from network, files, i.e. external world, then I > > validate it, report errors of some missing fields, fix another one > > (which can be fixed, for example, replace Nothing with `Just > > default_value` or even I can fix `Just wrong` to `Just right`, etc, > > etc). After all of this, I know that I have "clean" data, so all my > > complex types now have `Just right_value` fields. But I need to > > process them as optional, with possible Nothing case! To avoid it I > > must create copies of `A`, `B`, etc, where `a1`, `b1` will be `B`, > > `C`, not `Maybe B`, `Maybe C`. Sure, it's not a case. > > > > After processing and filtering, I create, for example, some > > resulting objects: > > > > data Result { > > a :: A -- not Maybe! > > ... } > > > > And even more: `a::A` in `Result` (I know it, after filtering) will > > not contain Nothings, only `Just right_values`s. > > > > But each function which consumes `A` must do something with possible > > Nothing values even after filtering and fixing of `A`s. > > > > I have, for example, function: > > > > createResults :: [A] -> [Result] > > createResults alst = > > ... > > case of (a1 theA) -> > > Just right_value -> ... > > Nothing -> > > logError > > undefined -- can not happen > > > > Fun here is: that it happens (I found bug in my filtering > > code with this `undefined`). But now I thought about it: what is the > > idiomatic way to solve such situation? When you need to have: > > > > - COMPLEX type WITH Maybes > > - the same type WITHOUT Maybes > > > > Alternative is to keep this Maybes to the very end of processing, > > what I don't like. Or to have types copies, which is more terrible, > > sure. > > > > PS. I threw IOs away to show only the crux of the problem. > > > > --- > > Cheers, > > Paul > > _______________________________________________ > > Beginners mailing list > > Beginners at haskell.org > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > From raabe at froglogic.com Thu Jul 6 10:02:12 2017 From: raabe at froglogic.com (Frerich Raabe) Date: Thu, 06 Jul 2017 12:02:12 +0200 Subject: [Haskell-beginners] Get rid of Maybes in complex types In-Reply-To: <20170706111255.1d6695b8@Pavel> References: <20170706111255.1d6695b8@Pavel> Message-ID: <17d148352ca50aadd7821e4fd19ea4ea@froglogic.com> On 2017-07-06 10:12, Baa wrote: > Consider, I retrieve from external source some data. Internally it's > represented as some complex type with `Maybe` fields, even more, some > of fields are record types and have `Maybe` fields too. They are > Maybe's because some information in this data can be missing (user > error or it not very valuable and can be skipped): > > data A = A { > a1 :: Maybe B > ... } > data B = B { > b1 :: Maybe C > ... } > > I retrieve it from network, files, i.e. external world, then I validate > it, report errors of some missing fields, fix another one (which can be > fixed, for example, replace Nothing with `Just default_value` or even I > can fix `Just wrong` to `Just right`, etc, etc). After all of this, I > know that I have "clean" data, so all my complex types now have `Just > right_value` fields. But I need to process them as optional, with > possible Nothing case! To avoid it I must create copies of `A`, `B`, > etc, where `a1`, `b1` will be `B`, `C`, not `Maybe B`, `Maybe C`. Sure, > it's not a case. I understand that your data structures as sketched above are only needed for a short time, when reading/validating/fixing the input data - the rest of the program would either report an error (for unrecoverable problems) or process the validated data? In that case, maybe you can avoid using Maybe in your data types for things which definitely must be present completely but rather returning a 'Maybe' value from your function which retrieves the data, i.e.: retrieveData :: ByteString -> Maybe A Within 'retrieveData' you could then use different weakly-typed data structures which maybe only represent subsets of the data as you parse/validate/fix it. Not sure if/how that would work out, but maybe you could share some more concrete code (e.g. the actual logic for retrieving the data and the data types)? -- Frerich Raabe - raabe at froglogic.com www.froglogic.com - Multi-Platform GUI Testing From imantc at gmail.com Thu Jul 6 10:40:35 2017 From: imantc at gmail.com (Imants Cekusins) Date: Thu, 6 Jul 2017 13:40:35 +0300 Subject: [Haskell-beginners] Get rid of Maybes in complex types In-Reply-To: <20170706130105.4112f723@Pavel> References: <20170706111255.1d6695b8@Pavel> <20170706130105.4112f723@Pavel> Message-ID: how about a function (or a Monad Transformer) that checks values in one place: check::A Maybe -> Maybe (A Identity) after values were checked, the after-checked functions will deal with A Identity the end result would be Maybe out On 6 July 2017 at 13:01, Baa wrote: > But will it work if I switch from one monad to another? Actually, I > have something like piping/conduit, and if I switch items in pipe from > `A Maybe` to `A Idenitity` - will it work? Whether it will be compiled? > > Although I certainly can "map" items from one type to another... > Idea looks interesting sure :) > > > > Identity > > > > http://hackage.haskell.org/package/mtl-2.2.1/docs/ > Control-Monad-Identity.html > > > > may work: > > > > data A m = A { > > a1 :: m B > > } > > data B m = B { > > b1 :: m C > > ... } > > > > m: Maybe or Identity > > > > - any good? > > > > > > > > On 6 July 2017 at 11:12, Baa wrote: > > > > > Hello Dear List! > > > > > > Consider, I retrieve from external source some data. Internally it's > > > represented as some complex type with `Maybe` fields, even more, > > > some of fields are record types and have `Maybe` fields too. They > > > are Maybe's because some information in this data can be missing > > > (user error or it not very valuable and can be skipped): > > > > > > data A = A { > > > a1 :: Maybe B > > > ... } > > > data B = B { > > > b1 :: Maybe C > > > ... } > > > > > > I retrieve it from network, files, i.e. external world, then I > > > validate it, report errors of some missing fields, fix another one > > > (which can be fixed, for example, replace Nothing with `Just > > > default_value` or even I can fix `Just wrong` to `Just right`, etc, > > > etc). After all of this, I know that I have "clean" data, so all my > > > complex types now have `Just right_value` fields. But I need to > > > process them as optional, with possible Nothing case! To avoid it I > > > must create copies of `A`, `B`, etc, where `a1`, `b1` will be `B`, > > > `C`, not `Maybe B`, `Maybe C`. Sure, it's not a case. > > > > > > After processing and filtering, I create, for example, some > > > resulting objects: > > > > > > data Result { > > > a :: A -- not Maybe! > > > ... } > > > > > > And even more: `a::A` in `Result` (I know it, after filtering) will > > > not contain Nothings, only `Just right_values`s. > > > > > > But each function which consumes `A` must do something with possible > > > Nothing values even after filtering and fixing of `A`s. > > > > > > I have, for example, function: > > > > > > createResults :: [A] -> [Result] > > > createResults alst = > > > ... > > > case of (a1 theA) -> > > > Just right_value -> ... > > > Nothing -> > > > logError > > > undefined -- can not happen > > > > > > Fun here is: that it happens (I found bug in my filtering > > > code with this `undefined`). But now I thought about it: what is the > > > idiomatic way to solve such situation? When you need to have: > > > > > > - COMPLEX type WITH Maybes > > > - the same type WITHOUT Maybes > > > > > > Alternative is to keep this Maybes to the very end of processing, > > > what I don't like. Or to have types copies, which is more terrible, > > > sure. > > > > > > PS. I threw IOs away to show only the crux of the problem. > > > > > > --- > > > Cheers, > > > Paul > > > _______________________________________________ > > > Beginners mailing list > > > Beginners at haskell.org > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > > > > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: From aquagnu at gmail.com Thu Jul 6 11:13:56 2017 From: aquagnu at gmail.com (Baa) Date: Thu, 6 Jul 2017 14:13:56 +0300 Subject: [Haskell-beginners] Get rid of Maybes in complex types In-Reply-To: References: <20170706111255.1d6695b8@Pavel> <20170706130105.4112f723@Pavel> Message-ID: <20170706141356.086afe40@Pavel> Imants, I'm not sure that I understood signatures. Why check::A Maybe -> Maybe (A Identity) but not check::A Maybe -> A Identity ? To filter (Nothing items must be throw out)? No more reasons for it? > how about a function (or a Monad Transformer) that checks values in > one place: > > check::A Maybe -> Maybe (A Identity) > > after values were checked, the after-checked functions will deal with > A Identity > > the end result would be > Maybe out > > > > On 6 July 2017 at 13:01, Baa wrote: > > > But will it work if I switch from one monad to another? Actually, I > > have something like piping/conduit, and if I switch items in pipe > > from `A Maybe` to `A Idenitity` - will it work? Whether it will be > > compiled? > > > > Although I certainly can "map" items from one type to another... > > Idea looks interesting sure :) > > > > > > > Identity > > > > > > http://hackage.haskell.org/package/mtl-2.2.1/docs/ > > Control-Monad-Identity.html > > > > > > may work: > > > > > > data A m = A { > > > a1 :: m B > > > } > > > data B m = B { > > > b1 :: m C > > > ... } > > > > > > m: Maybe or Identity > > > > > > - any good? > > > > > > > > > > > > On 6 July 2017 at 11:12, Baa wrote: > > > > > > > Hello Dear List! > > > > > > > > Consider, I retrieve from external source some data. Internally > > > > it's represented as some complex type with `Maybe` fields, even > > > > more, some of fields are record types and have `Maybe` fields > > > > too. They are Maybe's because some information in this data can > > > > be missing (user error or it not very valuable and can be > > > > skipped): > > > > > > > > data A = A { > > > > a1 :: Maybe B > > > > ... } > > > > data B = B { > > > > b1 :: Maybe C > > > > ... } > > > > > > > > I retrieve it from network, files, i.e. external world, then I > > > > validate it, report errors of some missing fields, fix another > > > > one (which can be fixed, for example, replace Nothing with `Just > > > > default_value` or even I can fix `Just wrong` to `Just right`, > > > > etc, etc). After all of this, I know that I have "clean" data, > > > > so all my complex types now have `Just right_value` fields. But > > > > I need to process them as optional, with possible Nothing case! > > > > To avoid it I must create copies of `A`, `B`, etc, where `a1`, > > > > `b1` will be `B`, `C`, not `Maybe B`, `Maybe C`. Sure, it's not > > > > a case. > > > > > > > > After processing and filtering, I create, for example, some > > > > resulting objects: > > > > > > > > data Result { > > > > a :: A -- not Maybe! > > > > ... } > > > > > > > > And even more: `a::A` in `Result` (I know it, after filtering) > > > > will not contain Nothings, only `Just right_values`s. > > > > > > > > But each function which consumes `A` must do something with > > > > possible Nothing values even after filtering and fixing of `A`s. > > > > > > > > I have, for example, function: > > > > > > > > createResults :: [A] -> [Result] > > > > createResults alst = > > > > ... > > > > case of (a1 theA) -> > > > > Just right_value -> ... > > > > Nothing -> > > > > logError > > > > undefined -- can not happen > > > > > > > > Fun here is: that it happens (I found bug in my filtering > > > > code with this `undefined`). But now I thought about it: what > > > > is the idiomatic way to solve such situation? When you need to > > > > have: > > > > > > > > - COMPLEX type WITH Maybes > > > > - the same type WITHOUT Maybes > > > > > > > > Alternative is to keep this Maybes to the very end of > > > > processing, what I don't like. Or to have types copies, which > > > > is more terrible, sure. > > > > > > > > PS. I threw IOs away to show only the crux of the problem. > > > > > > > > --- > > > > Cheers, > > > > Paul > > > > _______________________________________________ > > > > Beginners mailing list > > > > Beginners at haskell.org > > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > > > > > > > _______________________________________________ > > Beginners mailing list > > Beginners at haskell.org > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > From imantc at gmail.com Thu Jul 6 11:17:17 2017 From: imantc at gmail.com (Imants Cekusins) Date: Thu, 6 Jul 2017 14:17:17 +0300 Subject: [Haskell-beginners] Get rid of Maybes in complex types In-Reply-To: <20170706141356.086afe40@Pavel> References: <20170706111255.1d6695b8@Pavel> <20170706130105.4112f723@Pavel> <20170706141356.086afe40@Pavel> Message-ID: > Why.. what would check::A Maybe -> A Identity do if some A field were Nothing? fill in a default value? On 6 July 2017 at 14:13, Baa wrote: > Imants, I'm not sure that I understood signatures. > > Why > check::A Maybe -> Maybe (A Identity) > > but not > check::A Maybe -> A Identity > > ? > > To filter (Nothing items must be throw out)? No more reasons for it? > > > > how about a function (or a Monad Transformer) that checks values in > > one place: > > > > check::A Maybe -> Maybe (A Identity) > > > > after values were checked, the after-checked functions will deal with > > A Identity > > > > the end result would be > > Maybe out > > > > > > > > On 6 July 2017 at 13:01, Baa wrote: > > > > > But will it work if I switch from one monad to another? Actually, I > > > have something like piping/conduit, and if I switch items in pipe > > > from `A Maybe` to `A Idenitity` - will it work? Whether it will be > > > compiled? > > > > > > Although I certainly can "map" items from one type to another... > > > Idea looks interesting sure :) > > > > > > > > > > Identity > > > > > > > > http://hackage.haskell.org/package/mtl-2.2.1/docs/ > > > Control-Monad-Identity.html > > > > > > > > may work: > > > > > > > > data A m = A { > > > > a1 :: m B > > > > } > > > > data B m = B { > > > > b1 :: m C > > > > ... } > > > > > > > > m: Maybe or Identity > > > > > > > > - any good? > > > > > > > > > > > > > > > > On 6 July 2017 at 11:12, Baa wrote: > > > > > > > > > Hello Dear List! > > > > > > > > > > Consider, I retrieve from external source some data. Internally > > > > > it's represented as some complex type with `Maybe` fields, even > > > > > more, some of fields are record types and have `Maybe` fields > > > > > too. They are Maybe's because some information in this data can > > > > > be missing (user error or it not very valuable and can be > > > > > skipped): > > > > > > > > > > data A = A { > > > > > a1 :: Maybe B > > > > > ... } > > > > > data B = B { > > > > > b1 :: Maybe C > > > > > ... } > > > > > > > > > > I retrieve it from network, files, i.e. external world, then I > > > > > validate it, report errors of some missing fields, fix another > > > > > one (which can be fixed, for example, replace Nothing with `Just > > > > > default_value` or even I can fix `Just wrong` to `Just right`, > > > > > etc, etc). After all of this, I know that I have "clean" data, > > > > > so all my complex types now have `Just right_value` fields. But > > > > > I need to process them as optional, with possible Nothing case! > > > > > To avoid it I must create copies of `A`, `B`, etc, where `a1`, > > > > > `b1` will be `B`, `C`, not `Maybe B`, `Maybe C`. Sure, it's not > > > > > a case. > > > > > > > > > > After processing and filtering, I create, for example, some > > > > > resulting objects: > > > > > > > > > > data Result { > > > > > a :: A -- not Maybe! > > > > > ... } > > > > > > > > > > And even more: `a::A` in `Result` (I know it, after filtering) > > > > > will not contain Nothings, only `Just right_values`s. > > > > > > > > > > But each function which consumes `A` must do something with > > > > > possible Nothing values even after filtering and fixing of `A`s. > > > > > > > > > > I have, for example, function: > > > > > > > > > > createResults :: [A] -> [Result] > > > > > createResults alst = > > > > > ... > > > > > case of (a1 theA) -> > > > > > Just right_value -> ... > > > > > Nothing -> > > > > > logError > > > > > undefined -- can not happen > > > > > > > > > > Fun here is: that it happens (I found bug in my filtering > > > > > code with this `undefined`). But now I thought about it: what > > > > > is the idiomatic way to solve such situation? When you need to > > > > > have: > > > > > > > > > > - COMPLEX type WITH Maybes > > > > > - the same type WITHOUT Maybes > > > > > > > > > > Alternative is to keep this Maybes to the very end of > > > > > processing, what I don't like. Or to have types copies, which > > > > > is more terrible, sure. > > > > > > > > > > PS. I threw IOs away to show only the crux of the problem. > > > > > > > > > > --- > > > > > Cheers, > > > > > Paul > > > > > _______________________________________________ > > > > > Beginners mailing list > > > > > Beginners at haskell.org > > > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > > > > > > > > > > _______________________________________________ > > > Beginners mailing list > > > Beginners at haskell.org > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > > > > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: From aquagnu at gmail.com Thu Jul 6 11:22:59 2017 From: aquagnu at gmail.com (Baa) Date: Thu, 6 Jul 2017 14:22:59 +0300 Subject: [Haskell-beginners] Get rid of Maybes in complex types In-Reply-To: <17d148352ca50aadd7821e4fd19ea4ea@froglogic.com> References: <20170706111255.1d6695b8@Pavel> <17d148352ca50aadd7821e4fd19ea4ea@froglogic.com> Message-ID: <20170706142259.40c1dfe0@Pavel> Unfortunately it's a lot of code and it's not open source :( As I understood you, function `retrieveData` should make a final decision: to be or not to be? It's idea too, but possible will lead to more refactoring. Thu, 06 Jul 2017 12:02:12 +0200 Frerich Raabe wrote: > On 2017-07-06 10:12, Baa wrote: > > Consider, I retrieve from external source some data. Internally it's > > represented as some complex type with `Maybe` fields, even more, > > some of fields are record types and have `Maybe` fields too. They > > are Maybe's because some information in this data can be missing > > (user error or it not very valuable and can be skipped): > > > > data A = A { > > a1 :: Maybe B > > ... } > > data B = B { > > b1 :: Maybe C > > ... } > > > > I retrieve it from network, files, i.e. external world, then I > > validate it, report errors of some missing fields, fix another one > > (which can be fixed, for example, replace Nothing with `Just > > default_value` or even I can fix `Just wrong` to `Just right`, etc, > > etc). After all of this, I know that I have "clean" data, so all my > > complex types now have `Just right_value` fields. But I need to > > process them as optional, with possible Nothing case! To avoid it I > > must create copies of `A`, `B`, etc, where `a1`, `b1` will be `B`, > > `C`, not `Maybe B`, `Maybe C`. Sure, it's not a case. > > I understand that your data structures as sketched above are only > needed for a short time, when reading/validating/fixing the input > data - the rest of the program would either report an error (for > unrecoverable problems) or process the validated data? > > In that case, maybe you can avoid using Maybe in your data types for > things which definitely must be present completely but rather > returning a 'Maybe' value from your function which retrieves the > data, i.e.: > > retrieveData :: ByteString -> Maybe A > > Within 'retrieveData' you could then use different weakly-typed data > structures which maybe only represent subsets of the data as you > parse/validate/fix it. Not sure if/how that would work out, but maybe > you could share some more concrete code (e.g. the actual logic for > retrieving the data and the data types)? > From aquagnu at gmail.com Thu Jul 6 11:33:25 2017 From: aquagnu at gmail.com (Baa) Date: Thu, 6 Jul 2017 14:33:25 +0300 Subject: [Haskell-beginners] Get rid of Maybes in complex types In-Reply-To: References: <20170706111255.1d6695b8@Pavel> <20170706130105.4112f723@Pavel> <20170706141356.086afe40@Pavel> Message-ID: <20170706143325.1b269d29@Pavel> Hmm, yes. `Nothing` becomes `Identity default_value`. Respectively `A Maybe` becomes `A Identity`. I'm not sure will it work but it looks alluringly ;) > > Why.. > > what would > check::A Maybe -> A Identity > > do if some A field were Nothing? fill in a default value? > > On 6 July 2017 at 14:13, Baa wrote: > > > Imants, I'm not sure that I understood signatures. > > > > Why > > check::A Maybe -> Maybe (A Identity) > > > > but not > > check::A Maybe -> A Identity > > > > ? > > > > To filter (Nothing items must be throw out)? No more reasons for it? > > > > > > > how about a function (or a Monad Transformer) that checks values > > > in one place: > > > > > > check::A Maybe -> Maybe (A Identity) > > > > > > after values were checked, the after-checked functions will deal > > > with A Identity > > > > > > the end result would be > > > Maybe out > > > > > > > > > > > > On 6 July 2017 at 13:01, Baa wrote: > > > > > > > But will it work if I switch from one monad to another? > > > > Actually, I have something like piping/conduit, and if I switch > > > > items in pipe from `A Maybe` to `A Idenitity` - will it work? > > > > Whether it will be compiled? > > > > > > > > Although I certainly can "map" items from one type to another... > > > > Idea looks interesting sure :) > > > > > > > > > > > > > Identity > > > > > > > > > > http://hackage.haskell.org/package/mtl-2.2.1/docs/ > > > > Control-Monad-Identity.html > > > > > > > > > > may work: > > > > > > > > > > data A m = A { > > > > > a1 :: m B > > > > > } > > > > > data B m = B { > > > > > b1 :: m C > > > > > ... } > > > > > > > > > > m: Maybe or Identity > > > > > > > > > > - any good? > > > > > > > > > > > > > > > > > > > > On 6 July 2017 at 11:12, Baa wrote: > > > > > > > > > > > Hello Dear List! > > > > > > > > > > > > Consider, I retrieve from external source some data. > > > > > > Internally it's represented as some complex type with > > > > > > `Maybe` fields, even more, some of fields are record types > > > > > > and have `Maybe` fields too. They are Maybe's because some > > > > > > information in this data can be missing (user error or it > > > > > > not very valuable and can be skipped): > > > > > > > > > > > > data A = A { > > > > > > a1 :: Maybe B > > > > > > ... } > > > > > > data B = B { > > > > > > b1 :: Maybe C > > > > > > ... } > > > > > > > > > > > > I retrieve it from network, files, i.e. external world, > > > > > > then I validate it, report errors of some missing fields, > > > > > > fix another one (which can be fixed, for example, replace > > > > > > Nothing with `Just default_value` or even I can fix `Just > > > > > > wrong` to `Just right`, etc, etc). After all of this, I > > > > > > know that I have "clean" data, so all my complex types now > > > > > > have `Just right_value` fields. But I need to process them > > > > > > as optional, with possible Nothing case! To avoid it I must > > > > > > create copies of `A`, `B`, etc, where `a1`, `b1` will be > > > > > > `B`, `C`, not `Maybe B`, `Maybe C`. Sure, it's not a case. > > > > > > > > > > > > After processing and filtering, I create, for example, some > > > > > > resulting objects: > > > > > > > > > > > > data Result { > > > > > > a :: A -- not Maybe! > > > > > > ... } > > > > > > > > > > > > And even more: `a::A` in `Result` (I know it, after > > > > > > filtering) will not contain Nothings, only `Just > > > > > > right_values`s. > > > > > > > > > > > > But each function which consumes `A` must do something with > > > > > > possible Nothing values even after filtering and fixing of > > > > > > `A`s. > > > > > > > > > > > > I have, for example, function: > > > > > > > > > > > > createResults :: [A] -> [Result] > > > > > > createResults alst = > > > > > > ... > > > > > > case of (a1 theA) -> > > > > > > Just right_value -> ... > > > > > > Nothing -> > > > > > > logError > > > > > > undefined -- can not happen > > > > > > > > > > > > Fun here is: that it happens (I found bug in my filtering > > > > > > code with this `undefined`). But now I thought about it: > > > > > > what is the idiomatic way to solve such situation? When you > > > > > > need to have: > > > > > > > > > > > > - COMPLEX type WITH Maybes > > > > > > - the same type WITHOUT Maybes > > > > > > > > > > > > Alternative is to keep this Maybes to the very end of > > > > > > processing, what I don't like. Or to have types copies, > > > > > > which is more terrible, sure. > > > > > > > > > > > > PS. I threw IOs away to show only the crux of the problem. > > > > > > > > > > > > --- > > > > > > Cheers, > > > > > > Paul > > > > > > _______________________________________________ > > > > > > Beginners mailing list > > > > > > Beginners at haskell.org > > > > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > > > > > > > > > > > > > _______________________________________________ > > > > Beginners mailing list > > > > Beginners at haskell.org > > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > > > > > > > _______________________________________________ > > Beginners mailing list > > Beginners at haskell.org > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > From imantc at gmail.com Thu Jul 6 11:37:52 2017 From: imantc at gmail.com (Imants Cekusins) Date: Thu, 6 Jul 2017 14:37:52 +0300 Subject: [Haskell-beginners] Get rid of Maybes in complex types In-Reply-To: <20170706143325.1b269d29@Pavel> References: <20170706111255.1d6695b8@Pavel> <20170706130105.4112f723@Pavel> <20170706141356.086afe40@Pavel> <20170706143325.1b269d29@Pavel> Message-ID: is it possible to replace Nothing with defaults when A, B are init'ed ? On 6 July 2017 at 14:33, Baa wrote: > Hmm, yes. `Nothing` becomes `Identity default_value`. Respectively `A > Maybe` becomes `A Identity`. I'm not sure will it work but it looks > alluringly ;) > > > > Why.. > > > > what would > > check::A Maybe -> A Identity > > > > do if some A field were Nothing? fill in a default value? > > > > On 6 July 2017 at 14:13, Baa wrote: > > > > > Imants, I'm not sure that I understood signatures. > > > > > > Why > > > check::A Maybe -> Maybe (A Identity) > > > > > > but not > > > check::A Maybe -> A Identity > > > > > > ? > > > > > > To filter (Nothing items must be throw out)? No more reasons for it? > > > > > > > > > > how about a function (or a Monad Transformer) that checks values > > > > in one place: > > > > > > > > check::A Maybe -> Maybe (A Identity) > > > > > > > > after values were checked, the after-checked functions will deal > > > > with A Identity > > > > > > > > the end result would be > > > > Maybe out > > > > > > > > > > > > > > > > On 6 July 2017 at 13:01, Baa wrote: > > > > > > > > > But will it work if I switch from one monad to another? > > > > > Actually, I have something like piping/conduit, and if I switch > > > > > items in pipe from `A Maybe` to `A Idenitity` - will it work? > > > > > Whether it will be compiled? > > > > > > > > > > Although I certainly can "map" items from one type to another... > > > > > Idea looks interesting sure :) > > > > > > > > > > > > > > > > Identity > > > > > > > > > > > > http://hackage.haskell.org/package/mtl-2.2.1/docs/ > > > > > Control-Monad-Identity.html > > > > > > > > > > > > may work: > > > > > > > > > > > > data A m = A { > > > > > > a1 :: m B > > > > > > } > > > > > > data B m = B { > > > > > > b1 :: m C > > > > > > ... } > > > > > > > > > > > > m: Maybe or Identity > > > > > > > > > > > > - any good? > > > > > > > > > > > > > > > > > > > > > > > > On 6 July 2017 at 11:12, Baa wrote: > > > > > > > > > > > > > Hello Dear List! > > > > > > > > > > > > > > Consider, I retrieve from external source some data. > > > > > > > Internally it's represented as some complex type with > > > > > > > `Maybe` fields, even more, some of fields are record types > > > > > > > and have `Maybe` fields too. They are Maybe's because some > > > > > > > information in this data can be missing (user error or it > > > > > > > not very valuable and can be skipped): > > > > > > > > > > > > > > data A = A { > > > > > > > a1 :: Maybe B > > > > > > > ... } > > > > > > > data B = B { > > > > > > > b1 :: Maybe C > > > > > > > ... } > > > > > > > > > > > > > > I retrieve it from network, files, i.e. external world, > > > > > > > then I validate it, report errors of some missing fields, > > > > > > > fix another one (which can be fixed, for example, replace > > > > > > > Nothing with `Just default_value` or even I can fix `Just > > > > > > > wrong` to `Just right`, etc, etc). After all of this, I > > > > > > > know that I have "clean" data, so all my complex types now > > > > > > > have `Just right_value` fields. But I need to process them > > > > > > > as optional, with possible Nothing case! To avoid it I must > > > > > > > create copies of `A`, `B`, etc, where `a1`, `b1` will be > > > > > > > `B`, `C`, not `Maybe B`, `Maybe C`. Sure, it's not a case. > > > > > > > > > > > > > > After processing and filtering, I create, for example, some > > > > > > > resulting objects: > > > > > > > > > > > > > > data Result { > > > > > > > a :: A -- not Maybe! > > > > > > > ... } > > > > > > > > > > > > > > And even more: `a::A` in `Result` (I know it, after > > > > > > > filtering) will not contain Nothings, only `Just > > > > > > > right_values`s. > > > > > > > > > > > > > > But each function which consumes `A` must do something with > > > > > > > possible Nothing values even after filtering and fixing of > > > > > > > `A`s. > > > > > > > > > > > > > > I have, for example, function: > > > > > > > > > > > > > > createResults :: [A] -> [Result] > > > > > > > createResults alst = > > > > > > > ... > > > > > > > case of (a1 theA) -> > > > > > > > Just right_value -> ... > > > > > > > Nothing -> > > > > > > > logError > > > > > > > undefined -- can not happen > > > > > > > > > > > > > > Fun here is: that it happens (I found bug in my filtering > > > > > > > code with this `undefined`). But now I thought about it: > > > > > > > what is the idiomatic way to solve such situation? When you > > > > > > > need to have: > > > > > > > > > > > > > > - COMPLEX type WITH Maybes > > > > > > > - the same type WITHOUT Maybes > > > > > > > > > > > > > > Alternative is to keep this Maybes to the very end of > > > > > > > processing, what I don't like. Or to have types copies, > > > > > > > which is more terrible, sure. > > > > > > > > > > > > > > PS. I threw IOs away to show only the crux of the problem. > > > > > > > > > > > > > > --- > > > > > > > Cheers, > > > > > > > Paul > > > > > > > _______________________________________________ > > > > > > > Beginners mailing list > > > > > > > Beginners at haskell.org > > > > > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > > > > > > > > > > > > > > > > _______________________________________________ > > > > > Beginners mailing list > > > > > Beginners at haskell.org > > > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > > > > > > > > > > _______________________________________________ > > > Beginners mailing list > > > Beginners at haskell.org > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > > > > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: From aquagnu at gmail.com Thu Jul 6 11:54:02 2017 From: aquagnu at gmail.com (Baa) Date: Thu, 6 Jul 2017 14:54:02 +0300 Subject: [Haskell-beginners] Get rid of Maybes in complex types In-Reply-To: References: <20170706111255.1d6695b8@Pavel> <20170706130105.4112f723@Pavel> <20170706141356.086afe40@Pavel> <20170706143325.1b269d29@Pavel> Message-ID: <20170706145402.33f7ca54@Pavel> Unfortunately, no. > is it possible to replace Nothing with defaults when A, B are > init'ed ? > > On 6 July 2017 at 14:33, Baa wrote: > > > Hmm, yes. `Nothing` becomes `Identity default_value`. Respectively > > `A Maybe` becomes `A Identity`. I'm not sure will it work but it > > looks alluringly ;) > > > > > > Why.. > > > > > > what would > > > check::A Maybe -> A Identity > > > > > > do if some A field were Nothing? fill in a default value? > > > > > > On 6 July 2017 at 14:13, Baa wrote: > > > > > > > Imants, I'm not sure that I understood signatures. > > > > > > > > Why > > > > check::A Maybe -> Maybe (A Identity) > > > > > > > > but not > > > > check::A Maybe -> A Identity > > > > > > > > ? > > > > > > > > To filter (Nothing items must be throw out)? No more reasons > > > > for it? > > > > > > > > > > > > > how about a function (or a Monad Transformer) that checks > > > > > values in one place: > > > > > > > > > > check::A Maybe -> Maybe (A Identity) > > > > > > > > > > after values were checked, the after-checked functions will > > > > > deal with A Identity > > > > > > > > > > the end result would be > > > > > Maybe out > > > > > > > > > > > > > > > > > > > > On 6 July 2017 at 13:01, Baa wrote: > > > > > > > > > > > But will it work if I switch from one monad to another? > > > > > > Actually, I have something like piping/conduit, and if I > > > > > > switch items in pipe from `A Maybe` to `A Idenitity` - will > > > > > > it work? Whether it will be compiled? > > > > > > > > > > > > Although I certainly can "map" items from one type to > > > > > > another... Idea looks interesting sure :) > > > > > > > > > > > > > > > > > > > Identity > > > > > > > > > > > > > > http://hackage.haskell.org/package/mtl-2.2.1/docs/ > > > > > > Control-Monad-Identity.html > > > > > > > > > > > > > > may work: > > > > > > > > > > > > > > data A m = A { > > > > > > > a1 :: m B > > > > > > > } > > > > > > > data B m = B { > > > > > > > b1 :: m C > > > > > > > ... } > > > > > > > > > > > > > > m: Maybe or Identity > > > > > > > > > > > > > > - any good? > > > > > > > > > > > > > > > > > > > > > > > > > > > > On 6 July 2017 at 11:12, Baa wrote: > > > > > > > > > > > > > > > Hello Dear List! > > > > > > > > > > > > > > > > Consider, I retrieve from external source some data. > > > > > > > > Internally it's represented as some complex type with > > > > > > > > `Maybe` fields, even more, some of fields are record > > > > > > > > types and have `Maybe` fields too. They are Maybe's > > > > > > > > because some information in this data can be missing > > > > > > > > (user error or it not very valuable and can be skipped): > > > > > > > > > > > > > > > > data A = A { > > > > > > > > a1 :: Maybe B > > > > > > > > ... } > > > > > > > > data B = B { > > > > > > > > b1 :: Maybe C > > > > > > > > ... } > > > > > > > > > > > > > > > > I retrieve it from network, files, i.e. external world, > > > > > > > > then I validate it, report errors of some missing > > > > > > > > fields, fix another one (which can be fixed, for > > > > > > > > example, replace Nothing with `Just default_value` or > > > > > > > > even I can fix `Just wrong` to `Just right`, etc, etc). > > > > > > > > After all of this, I know that I have "clean" data, so > > > > > > > > all my complex types now have `Just right_value` > > > > > > > > fields. But I need to process them as optional, with > > > > > > > > possible Nothing case! To avoid it I must create copies > > > > > > > > of `A`, `B`, etc, where `a1`, `b1` will be `B`, `C`, > > > > > > > > not `Maybe B`, `Maybe C`. Sure, it's not a case. > > > > > > > > > > > > > > > > After processing and filtering, I create, for example, > > > > > > > > some resulting objects: > > > > > > > > > > > > > > > > data Result { > > > > > > > > a :: A -- not Maybe! > > > > > > > > ... } > > > > > > > > > > > > > > > > And even more: `a::A` in `Result` (I know it, after > > > > > > > > filtering) will not contain Nothings, only `Just > > > > > > > > right_values`s. > > > > > > > > > > > > > > > > But each function which consumes `A` must do something > > > > > > > > with possible Nothing values even after filtering and > > > > > > > > fixing of `A`s. > > > > > > > > > > > > > > > > I have, for example, function: > > > > > > > > > > > > > > > > createResults :: [A] -> [Result] > > > > > > > > createResults alst = > > > > > > > > ... > > > > > > > > case of (a1 theA) -> > > > > > > > > Just right_value -> ... > > > > > > > > Nothing -> > > > > > > > > logError > > > > > > > > undefined -- can not happen > > > > > > > > > > > > > > > > Fun here is: that it happens (I found bug in my > > > > > > > > filtering code with this `undefined`). But now I > > > > > > > > thought about it: what is the idiomatic way to solve > > > > > > > > such situation? When you need to have: > > > > > > > > > > > > > > > > - COMPLEX type WITH Maybes > > > > > > > > - the same type WITHOUT Maybes > > > > > > > > > > > > > > > > Alternative is to keep this Maybes to the very end of > > > > > > > > processing, what I don't like. Or to have types copies, > > > > > > > > which is more terrible, sure. > > > > > > > > > > > > > > > > PS. I threw IOs away to show only the crux of the > > > > > > > > problem. > > > > > > > > > > > > > > > > --- > > > > > > > > Cheers, > > > > > > > > Paul > > > > > > > > _______________________________________________ > > > > > > > > Beginners mailing list > > > > > > > > Beginners at haskell.org > > > > > > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > > > > > > > > > > > > > > > > > > > _______________________________________________ > > > > > > Beginners mailing list > > > > > > Beginners at haskell.org > > > > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > > > > > > > > > > > > > _______________________________________________ > > > > Beginners mailing list > > > > Beginners at haskell.org > > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > > > > > > > _______________________________________________ > > Beginners mailing list > > Beginners at haskell.org > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > From sylvain at haskus.fr Thu Jul 6 13:09:17 2017 From: sylvain at haskus.fr (Sylvain Henry) Date: Thu, 6 Jul 2017 15:09:17 +0200 Subject: [Haskell-beginners] Get rid of Maybes in complex types In-Reply-To: <20170706111255.1d6695b8@Pavel> References: <20170706111255.1d6695b8@Pavel> Message-ID: <0edaaa31-0241-2a1d-ef98-1967e3b72b5d@haskus.fr> Hi, You can use something similar to "Trees that grows" in GHC: {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE UndecidableInstances #-} module Main where import Data.Maybe data Checked = Checked deriving (Show) data Unchecked = Unchecked deriving (Show) type family F a b :: * where F Unchecked b = Maybe b F Checked b = b -- data types are decorated with a phantom type indicating if they have been checked -- in which case "Maybe X" are replaced with "X" (see F above) data A c = A { a1 :: F c (B c) } data B c = B { b1 :: F c (C c) } data C c = C { c1 :: F c Int } deriving instance Show (F c (B c)) => Show (A c) deriving instance Show (F c (C c)) => Show (B c) deriving instance Show (F c Int) => Show (C c) class Checkable a where check :: a Unchecked -> a Checked instance Checkable A where check (A mb) = A (check (fromJust mb)) instance Checkable B where check (B mc) = B (check (fromJust mc)) instance Checkable C where check (C mi) = C (fromJust mi) main :: IO () main = do let a :: A Unchecked a = A (Just (B (Just (C (Just 10))))) a' :: A Checked a' = check a print a print a' $> ./Test A {a1 = Just (B {b1 = Just (C {c1 = Just 10})})} A {a1 = B {b1 = C {c1 = 10}}} Cheers, Sylvain On 06/07/2017 10:12, Baa wrote: > Hello Dear List! > > Consider, I retrieve from external source some data. Internally it's > represented as some complex type with `Maybe` fields, even more, some > of fields are record types and have `Maybe` fields too. They are > Maybe's because some information in this data can be missing (user > error or it not very valuable and can be skipped): > > data A = A { > a1 :: Maybe B > ... } > data B = B { > b1 :: Maybe C > ... } > > I retrieve it from network, files, i.e. external world, then I validate > it, report errors of some missing fields, fix another one (which can be > fixed, for example, replace Nothing with `Just default_value` or even I > can fix `Just wrong` to `Just right`, etc, etc). After all of this, I > know that I have "clean" data, so all my complex types now have `Just > right_value` fields. But I need to process them as optional, with > possible Nothing case! To avoid it I must create copies of `A`, `B`, > etc, where `a1`, `b1` will be `B`, `C`, not `Maybe B`, `Maybe C`. Sure, > it's not a case. > > After processing and filtering, I create, for example, some resulting > objects: > > data Result { > a :: A -- not Maybe! > ... } > > And even more: `a::A` in `Result` (I know it, after filtering) will not > contain Nothings, only `Just right_values`s. > > But each function which consumes `A` must do something with possible > Nothing values even after filtering and fixing of `A`s. > > I have, for example, function: > > createResults :: [A] -> [Result] > createResults alst = > ... > case of (a1 theA) -> > Just right_value -> ... > Nothing -> > logError > undefined -- can not happen > > Fun here is: that it happens (I found bug in my filtering > code with this `undefined`). But now I thought about it: what is the > idiomatic way to solve such situation? When you need to have: > > - COMPLEX type WITH Maybes > - the same type WITHOUT Maybes > > Alternative is to keep this Maybes to the very end of processing, what I > don't like. Or to have types copies, which is more terrible, sure. > > PS. I threw IOs away to show only the crux of the problem. > > --- > Cheers, > Paul > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners From imantc at gmail.com Thu Jul 6 13:37:05 2017 From: imantc at gmail.com (Imants Cekusins) Date: Thu, 6 Jul 2017 16:37:05 +0300 Subject: [Haskell-beginners] Get rid of Maybes in complex types In-Reply-To: <0edaaa31-0241-2a1d-ef98-1967e3b72b5d@haskus.fr> References: <20170706111255.1d6695b8@Pavel> <0edaaa31-0241-2a1d-ef98-1967e3b72b5d@haskus.fr> Message-ID: > "Trees that grows" this (type families), or Tagged http://hackage.haskell.org/package/tagged-0.8.5/docs/Data-Tagged.html data Checked = Checked Tagged Checked a On 6 July 2017 at 16:09, Sylvain Henry wrote: > Hi, > > You can use something similar to "Trees that grows" in GHC: > > {-# LANGUAGE TypeFamilies #-} > {-# LANGUAGE StandaloneDeriving #-} > {-# LANGUAGE FlexibleContexts #-} > {-# LANGUAGE UndecidableInstances #-} > > module Main where > > import Data.Maybe > > data Checked = Checked deriving (Show) > data Unchecked = Unchecked deriving (Show) > > type family F a b :: * where > F Unchecked b = Maybe b > F Checked b = b > > -- data types are decorated with a phantom type indicating if they have > been checked > -- in which case "Maybe X" are replaced with "X" (see F above) > data A c = A > { a1 :: F c (B c) > } > > data B c = B > { b1 :: F c (C c) > } > > data C c = C > { c1 :: F c Int > } > > deriving instance Show (F c (B c)) => Show (A c) > deriving instance Show (F c (C c)) => Show (B c) > deriving instance Show (F c Int) => Show (C c) > > class Checkable a where > check :: a Unchecked -> a Checked > > instance Checkable A where > check (A mb) = A (check (fromJust mb)) > > instance Checkable B where > check (B mc) = B (check (fromJust mc)) > > instance Checkable C where > check (C mi) = C (fromJust mi) > > main :: IO () > main = do > let > a :: A Unchecked > a = A (Just (B (Just (C (Just 10))))) > > a' :: A Checked > a' = check a > print a > print a' > > > $> ./Test > A {a1 = Just (B {b1 = Just (C {c1 = Just 10})})} > A {a1 = B {b1 = C {c1 = 10}}} > > > Cheers, > Sylvain > > > > On 06/07/2017 10:12, Baa wrote: > >> Hello Dear List! >> >> Consider, I retrieve from external source some data. Internally it's >> represented as some complex type with `Maybe` fields, even more, some >> of fields are record types and have `Maybe` fields too. They are >> Maybe's because some information in this data can be missing (user >> error or it not very valuable and can be skipped): >> >> data A = A { >> a1 :: Maybe B >> ... } >> data B = B { >> b1 :: Maybe C >> ... } >> >> I retrieve it from network, files, i.e. external world, then I validate >> it, report errors of some missing fields, fix another one (which can be >> fixed, for example, replace Nothing with `Just default_value` or even I >> can fix `Just wrong` to `Just right`, etc, etc). After all of this, I >> know that I have "clean" data, so all my complex types now have `Just >> right_value` fields. But I need to process them as optional, with >> possible Nothing case! To avoid it I must create copies of `A`, `B`, >> etc, where `a1`, `b1` will be `B`, `C`, not `Maybe B`, `Maybe C`. Sure, >> it's not a case. >> >> After processing and filtering, I create, for example, some resulting >> objects: >> >> data Result { >> a :: A -- not Maybe! >> ... } >> >> And even more: `a::A` in `Result` (I know it, after filtering) will not >> contain Nothings, only `Just right_values`s. >> >> But each function which consumes `A` must do something with possible >> Nothing values even after filtering and fixing of `A`s. >> >> I have, for example, function: >> >> createResults :: [A] -> [Result] >> createResults alst = >> ... >> case of (a1 theA) -> >> Just right_value -> ... >> Nothing -> >> logError >> undefined -- can not happen >> >> Fun here is: that it happens (I found bug in my filtering >> code with this `undefined`). But now I thought about it: what is the >> idiomatic way to solve such situation? When you need to have: >> >> - COMPLEX type WITH Maybes >> - the same type WITHOUT Maybes >> >> Alternative is to keep this Maybes to the very end of processing, what I >> don't like. Or to have types copies, which is more terrible, sure. >> >> PS. I threw IOs away to show only the crux of the problem. >> >> --- >> Cheers, >> Paul >> _______________________________________________ >> Beginners mailing list >> Beginners at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners >> > > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: From aquagnu at gmail.com Thu Jul 6 14:41:25 2017 From: aquagnu at gmail.com (Baa) Date: Thu, 6 Jul 2017 17:41:25 +0300 Subject: [Haskell-beginners] Get rid of Maybes in complex types In-Reply-To: <0edaaa31-0241-2a1d-ef98-1967e3b72b5d@haskus.fr> References: <20170706111255.1d6695b8@Pavel> <0edaaa31-0241-2a1d-ef98-1967e3b72b5d@haskus.fr> Message-ID: <20170706174125.0efbfa06@Pavel> Hello, Sylvain. Hmm, it's very interesting. Funny is that I already have tagged items but tags are run-time values, not compile time (types) :-) but this is a different. Problem was to make: A-with-maybes -> A-without-maybes Phantom type as flag and "clearing" of Maybe with family-type-with-maybes -> family-type-without-maybes looks promisingly. Another advantage, as I understand, is that I continue to use Just as a constructor for `a1` value, without to wrap it in something else, right? This seems to be a solution. Thank you and all others for your answers!! --- Best regards, Paul В Thu, 6 Jul 2017 15:09:17 +0200 Sylvain Henry wrote: > Hi, > > You can use something similar to "Trees that grows" in GHC: > > {-# LANGUAGE TypeFamilies #-} > {-# LANGUAGE StandaloneDeriving #-} > {-# LANGUAGE FlexibleContexts #-} > {-# LANGUAGE UndecidableInstances #-} > > module Main where > > import Data.Maybe > > data Checked = Checked deriving (Show) > data Unchecked = Unchecked deriving (Show) > > type family F a b :: * where > F Unchecked b = Maybe b > F Checked b = b > > -- data types are decorated with a phantom type indicating if they > have been checked > -- in which case "Maybe X" are replaced with "X" (see F above) > data A c = A > { a1 :: F c (B c) > } > > data B c = B > { b1 :: F c (C c) > } > > data C c = C > { c1 :: F c Int > } > > deriving instance Show (F c (B c)) => Show (A c) > deriving instance Show (F c (C c)) => Show (B c) > deriving instance Show (F c Int) => Show (C c) > > class Checkable a where > check :: a Unchecked -> a Checked > > instance Checkable A where > check (A mb) = A (check (fromJust mb)) > > instance Checkable B where > check (B mc) = B (check (fromJust mc)) > > instance Checkable C where > check (C mi) = C (fromJust mi) > > main :: IO () > main = do > let > a :: A Unchecked > a = A (Just (B (Just (C (Just 10))))) > > a' :: A Checked > a' = check a > print a > print a' > > > $> ./Test > A {a1 = Just (B {b1 = Just (C {c1 = Just 10})})} > A {a1 = B {b1 = C {c1 = 10}}} > > > Cheers, > Sylvain > > > On 06/07/2017 10:12, Baa wrote: > > Hello Dear List! > > > > Consider, I retrieve from external source some data. Internally it's > > represented as some complex type with `Maybe` fields, even more, > > some of fields are record types and have `Maybe` fields too. They > > are Maybe's because some information in this data can be missing > > (user error or it not very valuable and can be skipped): > > > > data A = A { > > a1 :: Maybe B > > ... } > > data B = B { > > b1 :: Maybe C > > ... } > > > > I retrieve it from network, files, i.e. external world, then I > > validate it, report errors of some missing fields, fix another one > > (which can be fixed, for example, replace Nothing with `Just > > default_value` or even I can fix `Just wrong` to `Just right`, etc, > > etc). After all of this, I know that I have "clean" data, so all my > > complex types now have `Just right_value` fields. But I need to > > process them as optional, with possible Nothing case! To avoid it I > > must create copies of `A`, `B`, etc, where `a1`, `b1` will be `B`, > > `C`, not `Maybe B`, `Maybe C`. Sure, it's not a case. > > > > After processing and filtering, I create, for example, some > > resulting objects: > > > > data Result { > > a :: A -- not Maybe! > > ... } > > > > And even more: `a::A` in `Result` (I know it, after filtering) will > > not contain Nothings, only `Just right_values`s. > > > > But each function which consumes `A` must do something with possible > > Nothing values even after filtering and fixing of `A`s. > > > > I have, for example, function: > > > > createResults :: [A] -> [Result] > > createResults alst = > > ... > > case of (a1 theA) -> > > Just right_value -> ... > > Nothing -> > > logError > > undefined -- can not happen > > > > Fun here is: that it happens (I found bug in my filtering > > code with this `undefined`). But now I thought about it: what is the > > idiomatic way to solve such situation? When you need to have: > > > > - COMPLEX type WITH Maybes > > - the same type WITHOUT Maybes > > > > Alternative is to keep this Maybes to the very end of processing, > > what I don't like. Or to have types copies, which is more terrible, > > sure. > > > > PS. I threw IOs away to show only the crux of the problem. > > > > --- > > Cheers, > > Paul > > _______________________________________________ > > Beginners mailing list > > Beginners at haskell.org > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners From patrick.browne at dit.ie Fri Jul 7 22:23:25 2017 From: patrick.browne at dit.ie (PATRICK BROWNE) Date: Fri, 7 Jul 2017 23:23:25 +0100 Subject: [Haskell-beginners] case statement and guarded equations Message-ID: In the case statement for the half function I think variable m is bound to the value of (snd (half (n - 1)). With this assumption, I have have written a guarded version called half1. Is it always possible to write case statements as a set of conditional equations? My intuition is that this should be possible and that the guarded version reduces pattern matching? Thanks, Pat data EvenOdd = Even | Odd deriving (Show,Eq) half 0 = (Even,0) half n = case half (n-1) of (Even,m) -> (Odd,m) (Odd,m) -> (Even,m+1) half1 0 = (Even , 0) half1 n | (fst (half (n - 1)) == Even) = (Odd , (snd (half (n - 1)))) half1 n | (fst (half (n - 1)) == Odd) = (Even , ((snd (half (n - 1))) + 1)) -- This email originated from DIT. If you received this email in error, please delete it from your system. Please note that if you are not the named addressee, disclosing, copying, distributing or taking any action based on the contents of this email or attachments is prohibited. www.dit.ie Is ó ITBÁC a tháinig an ríomhphost seo. Má fuair tú an ríomhphost seo trí earráid, scrios de do chóras é le do thoil. Tabhair ar aird, mura tú an seolaí ainmnithe, go bhfuil dianchosc ar aon nochtadh, aon chóipeáil, aon dáileadh nó ar aon ghníomh a dhéanfar bunaithe ar an ábhar atá sa ríomhphost nó sna hiatáin seo. www.dit.ie Tá ITBÁC ag aistriú go Gráinseach Ghormáin – DIT is on the move to Grangegorman -------------- next part -------------- An HTML attachment was scrubbed... URL: From rein.henrichs at gmail.com Fri Jul 7 22:38:06 2017 From: rein.henrichs at gmail.com (Rein Henrichs) Date: Fri, 07 Jul 2017 22:38:06 +0000 Subject: [Haskell-beginners] case statement and guarded equations In-Reply-To: References: Message-ID: Quoting the report[1], "A boolean guard, g, is semantically equivalent to the pattern guard True <- g," which means the answer is "Yes". A boolean guard is equivalent to a pattern match. A predicate involving ==, however, introduces an Eq constraint that would not be required by pattern matching. For a properly equivalent guard, you need to write your predicates using pattern matching isEven Even = True isEven _ = False to avoid the spurious Eq constraint. [1] https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-460003.13 -------------- next part -------------- An HTML attachment was scrubbed... URL: From rein.henrichs at gmail.com Fri Jul 7 22:40:20 2017 From: rein.henrichs at gmail.com (Rein Henrichs) Date: Fri, 07 Jul 2017 22:40:20 +0000 Subject: [Haskell-beginners] case statement and guarded equations In-Reply-To: References: Message-ID: I'll also mention that GHC's exhaustiveness checker will mark the pattern match as exhaustive (since EvenOdd must be either Even or Odd and both cases are given) but warn about the two guards since it doesn't know that they form a dichotomy. You can use `otherwise`, which is just another name for True, to convince GHC that your guards are exhaustive. On Fri, Jul 7, 2017 at 3:38 PM Rein Henrichs wrote: > Quoting the report[1], "A boolean guard, g, is semantically equivalent to > the pattern guard True <- g," which means the answer is "Yes". A boolean > guard is equivalent to a pattern match. A predicate involving ==, however, > introduces an Eq constraint that would not be required by pattern matching. > For a properly equivalent guard, you need to write your predicates using > pattern matching > > isEven Even = True > isEven _ = False > > to avoid the spurious Eq constraint. > > [1] > https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-460003.13 > -------------- next part -------------- An HTML attachment was scrubbed... URL: From rein.henrichs at gmail.com Fri Jul 7 22:42:10 2017 From: rein.henrichs at gmail.com (Rein Henrichs) Date: Fri, 07 Jul 2017 22:42:10 +0000 Subject: [Haskell-beginners] case statement and guarded equations In-Reply-To: References: Message-ID: Sorry for the multiple responses. I just wanted to mention that the equivalent guards do not "reduce pattern matching", they just move it around a bit. Pattern matching is fundamental and pretty much everything involved in evaluation desugars to pattern matching eventually. On Fri, Jul 7, 2017 at 3:40 PM Rein Henrichs wrote: > I'll also mention that GHC's exhaustiveness checker will mark the pattern > match as exhaustive (since EvenOdd must be either Even or Odd and both > cases are given) but warn about the two guards since it doesn't know that > they form a dichotomy. You can use `otherwise`, which is just another name > for True, to convince GHC that your guards are exhaustive. > > On Fri, Jul 7, 2017 at 3:38 PM Rein Henrichs > wrote: > >> Quoting the report[1], "A boolean guard, g, is semantically equivalent to >> the pattern guard True <- g," which means the answer is "Yes". A boolean >> guard is equivalent to a pattern match. A predicate involving ==, however, >> introduces an Eq constraint that would not be required by pattern matching. >> For a properly equivalent guard, you need to write your predicates using >> pattern matching >> >> isEven Even = True >> isEven _ = False >> >> to avoid the spurious Eq constraint. >> >> [1] >> https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-460003.13 >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From rmason at mun.ca Sat Jul 8 11:19:39 2017 From: rmason at mun.ca (Roger Mason) Date: Sat, 08 Jul 2017 08:49:39 -0230 Subject: [Haskell-beginners] using Shake to compile c++ Message-ID: Hello, I am trying the Shake build system to compile some c++. I would appreciate some advice on how to use the result of a call to pkg-config in constructing a compiler command. This is what I have currently in Build.hs: import Development.Shake import Development.Shake.Command import Development.Shake.FilePath import Development.Shake.Util main :: IO () main = shakeArgs shakeOptions{shakeFiles="bin"} $ do want ["bin/makelist", "bin/makejpeg" <.> exe] phony "clean" $ do putNormal "Cleaning files in _build" removeFilesAfter "bin" ["//*"] "bin/makelist" <.> exe %> \out -> do cs <- getDirectoryFiles "" ["src/MakeList.cxx"] let os = ["objects" c -<.> "o" | c <- cs] need os cmd "c++ -o" [out] os "bin/makejpeg" <.> exe %> \out -> do cs <- getDirectoryFiles "" ["src/MakeJpeg.cxx"] let os = ["objects" c -<.> "o" | c <- cs] need os cmd "c++ -o" [out] os "objects//*.o" %> \out -> do let c = dropDirectory1 $ out -<.> "cxx" let m = out -<.> "m" let i = cmd "pkg-config glib-2.0 --cflags" () <- cmd "c++ -c" [c] "-o" [out] "-MMD -MF" [m] [i] needMakefileDependencies m This is the output from 'stack runhaskell Build.sh': Build.hs:29:17: error: * Ambiguous type variable `t0' arising from a use of `cmd' prevents the constraint `(CmdArguments t0)' from being solved. Relevant bindings include i :: t0 (bound at Build.hs:29:13) Probable fix: use a type annotation to specify what `t0' should be. These potential instances exist: instance CmdResult r => CmdArguments (IO r) -- Defined in `Development.Shake.Command' instance CmdResult r => CmdArguments (Action r) -- Defined in `Development.Shake.Command' instance (Development.Shake.Command.Arg a, CmdArguments r) => CmdArguments (a -> r) -- Defined in `Development.Shake.Command' ...plus one other (use -fprint-potential-instances to see them all) * In the expression: cmd "pkg-config glib-2.0 --cflags" In an equation for `i': i = cmd "pkg-config glib-2.0 --cflags" In the expression: do { let c = dropDirectory1 $ out -<.> "cxx"; let m = out -<.> "m"; let i = cmd "pkg-config glib-2.0 --cflags"; () <- cmd "c++ -c" [c] "-o" [out] "-MMD -MF" [m] [i]; .... } Build.hs:30:15: error: * Ambiguous type variable `t0' arising from a use of `cmd' prevents the constraint `(Development.Shake.Command.Arg [t0])' from being solved. Relevant bindings include i :: t0 (bound at Build.hs:29:13) Probable fix: use a type annotation to specify what `t0' should be. These potential instances exist: instance Development.Shake.Command.Arg [CmdOption] -- Defined in `Development.Shake.Command' instance Development.Shake.Command.Arg [String] -- Defined in `Development.Shake.Command' instance Development.Shake.Command.Arg String -- Defined in `Development.Shake.Command' * In a stmt of a 'do' block: () <- cmd "c++ -c" [c] "-o" [out] "-MMD -MF" [m] [i] In the expression: do { let c = dropDirectory1 $ out -<.> "cxx"; let m = out -<.> "m"; let i = cmd "pkg-config glib-2.0 --cflags"; () <- cmd "c++ -c" [c] "-o" [out] "-MMD -MF" [m] [i]; .... } In the second argument of `(%>)', namely `\ out -> do { let ...; let ...; .... }' I would appreciate any help in getting the output of the call to pkg-config into the compiler invocation. Thanks, Roger From toad3k at gmail.com Sat Jul 8 11:37:58 2017 From: toad3k at gmail.com (David McBride) Date: Sat, 8 Jul 2017 07:37:58 -0400 Subject: [Haskell-beginners] using Shake to compile c++ In-Reply-To: References: Message-ID: The easy option is to just use command instead of cmd. Variadic functions are always a little weird to type check. command_ [] "pkg-config" ["glib-2.0","--cflags"] That will *probably* solve the ambiguity in both lines, but I haven't tested. On Sat, Jul 8, 2017 at 7:19 AM, Roger Mason wrote: > Hello, > > I am trying the Shake build system to compile some c++. I would > appreciate some advice on how to use the result of a call to pkg-config > in constructing a compiler command. This is what I have currently in Build.hs: > > import Development.Shake > import Development.Shake.Command > import Development.Shake.FilePath > import Development.Shake.Util > > main :: IO () > main = shakeArgs shakeOptions{shakeFiles="bin"} $ do > want ["bin/makelist", "bin/makejpeg" <.> exe] > > phony "clean" $ do > putNormal "Cleaning files in _build" > removeFilesAfter "bin" ["//*"] > > "bin/makelist" <.> exe %> \out -> do > cs <- getDirectoryFiles "" ["src/MakeList.cxx"] > let os = ["objects" c -<.> "o" | c <- cs] > need os > cmd "c++ -o" [out] os > > "bin/makejpeg" <.> exe %> \out -> do > cs <- getDirectoryFiles "" ["src/MakeJpeg.cxx"] > let os = ["objects" c -<.> "o" | c <- cs] > need os > cmd "c++ -o" [out] os > > "objects//*.o" %> \out -> do > let c = dropDirectory1 $ out -<.> "cxx" > let m = out -<.> "m" > let i = cmd "pkg-config glib-2.0 --cflags" > () <- cmd "c++ -c" [c] "-o" [out] "-MMD -MF" [m] [i] > needMakefileDependencies m > > This is the output from 'stack runhaskell Build.sh': > > Build.hs:29:17: error: > * Ambiguous type variable `t0' arising from a use of `cmd' > prevents the constraint `(CmdArguments t0)' from being solved. > Relevant bindings include i :: t0 (bound at Build.hs:29:13) > Probable fix: use a type annotation to specify what `t0' should be. > These potential instances exist: > instance CmdResult r => CmdArguments (IO r) > -- Defined in `Development.Shake.Command' > instance CmdResult r => CmdArguments (Action r) > -- Defined in `Development.Shake.Command' > instance (Development.Shake.Command.Arg a, CmdArguments r) => > CmdArguments (a -> r) > -- Defined in `Development.Shake.Command' > ...plus one other > (use -fprint-potential-instances to see them all) > * In the expression: cmd "pkg-config glib-2.0 --cflags" > In an equation for `i': i = cmd "pkg-config glib-2.0 --cflags" > In the expression: > do { let c = dropDirectory1 $ out -<.> "cxx"; > let m = out -<.> "m"; > let i = cmd "pkg-config glib-2.0 --cflags"; > () <- cmd "c++ -c" [c] "-o" [out] "-MMD -MF" [m] [i]; > .... } > > Build.hs:30:15: error: > * Ambiguous type variable `t0' arising from a use of `cmd' > prevents the constraint `(Development.Shake.Command.Arg > [t0])' from being solved. > Relevant bindings include i :: t0 (bound at Build.hs:29:13) > Probable fix: use a type annotation to specify what `t0' should be. > These potential instances exist: > instance Development.Shake.Command.Arg [CmdOption] > -- Defined in `Development.Shake.Command' > instance Development.Shake.Command.Arg [String] > -- Defined in `Development.Shake.Command' > instance Development.Shake.Command.Arg String > -- Defined in `Development.Shake.Command' > * In a stmt of a 'do' block: > () <- cmd "c++ -c" [c] "-o" [out] "-MMD -MF" [m] [i] > In the expression: > do { let c = dropDirectory1 $ out -<.> "cxx"; > let m = out -<.> "m"; > let i = cmd "pkg-config glib-2.0 --cflags"; > () <- cmd "c++ -c" [c] "-o" [out] "-MMD -MF" [m] [i]; > .... } > In the second argument of `(%>)', namely > `\ out > -> do { let ...; > let ...; > .... }' > > I would appreciate any help in getting the output of the call to > pkg-config into the compiler invocation. > > Thanks, > Roger > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners From toad3k at gmail.com Sat Jul 8 11:38:24 2017 From: toad3k at gmail.com (David McBride) Date: Sat, 8 Jul 2017 07:38:24 -0400 Subject: [Haskell-beginners] using Shake to compile c++ In-Reply-To: References: Message-ID: Sorry that should have been command, not command_ which is very different. On Sat, Jul 8, 2017 at 7:37 AM, David McBride wrote: > The easy option is to just use command instead of cmd. Variadic > functions are always a little weird to type check. > > command_ [] "pkg-config" ["glib-2.0","--cflags"] > > That will *probably* solve the ambiguity in both lines, but I haven't tested. > > On Sat, Jul 8, 2017 at 7:19 AM, Roger Mason wrote: >> Hello, >> >> I am trying the Shake build system to compile some c++. I would >> appreciate some advice on how to use the result of a call to pkg-config >> in constructing a compiler command. This is what I have currently in Build.hs: >> >> import Development.Shake >> import Development.Shake.Command >> import Development.Shake.FilePath >> import Development.Shake.Util >> >> main :: IO () >> main = shakeArgs shakeOptions{shakeFiles="bin"} $ do >> want ["bin/makelist", "bin/makejpeg" <.> exe] >> >> phony "clean" $ do >> putNormal "Cleaning files in _build" >> removeFilesAfter "bin" ["//*"] >> >> "bin/makelist" <.> exe %> \out -> do >> cs <- getDirectoryFiles "" ["src/MakeList.cxx"] >> let os = ["objects" c -<.> "o" | c <- cs] >> need os >> cmd "c++ -o" [out] os >> >> "bin/makejpeg" <.> exe %> \out -> do >> cs <- getDirectoryFiles "" ["src/MakeJpeg.cxx"] >> let os = ["objects" c -<.> "o" | c <- cs] >> need os >> cmd "c++ -o" [out] os >> >> "objects//*.o" %> \out -> do >> let c = dropDirectory1 $ out -<.> "cxx" >> let m = out -<.> "m" >> let i = cmd "pkg-config glib-2.0 --cflags" >> () <- cmd "c++ -c" [c] "-o" [out] "-MMD -MF" [m] [i] >> needMakefileDependencies m >> >> This is the output from 'stack runhaskell Build.sh': >> >> Build.hs:29:17: error: >> * Ambiguous type variable `t0' arising from a use of `cmd' >> prevents the constraint `(CmdArguments t0)' from being solved. >> Relevant bindings include i :: t0 (bound at Build.hs:29:13) >> Probable fix: use a type annotation to specify what `t0' should be. >> These potential instances exist: >> instance CmdResult r => CmdArguments (IO r) >> -- Defined in `Development.Shake.Command' >> instance CmdResult r => CmdArguments (Action r) >> -- Defined in `Development.Shake.Command' >> instance (Development.Shake.Command.Arg a, CmdArguments r) => >> CmdArguments (a -> r) >> -- Defined in `Development.Shake.Command' >> ...plus one other >> (use -fprint-potential-instances to see them all) >> * In the expression: cmd "pkg-config glib-2.0 --cflags" >> In an equation for `i': i = cmd "pkg-config glib-2.0 --cflags" >> In the expression: >> do { let c = dropDirectory1 $ out -<.> "cxx"; >> let m = out -<.> "m"; >> let i = cmd "pkg-config glib-2.0 --cflags"; >> () <- cmd "c++ -c" [c] "-o" [out] "-MMD -MF" [m] [i]; >> .... } >> >> Build.hs:30:15: error: >> * Ambiguous type variable `t0' arising from a use of `cmd' >> prevents the constraint `(Development.Shake.Command.Arg >> [t0])' from being solved. >> Relevant bindings include i :: t0 (bound at Build.hs:29:13) >> Probable fix: use a type annotation to specify what `t0' should be. >> These potential instances exist: >> instance Development.Shake.Command.Arg [CmdOption] >> -- Defined in `Development.Shake.Command' >> instance Development.Shake.Command.Arg [String] >> -- Defined in `Development.Shake.Command' >> instance Development.Shake.Command.Arg String >> -- Defined in `Development.Shake.Command' >> * In a stmt of a 'do' block: >> () <- cmd "c++ -c" [c] "-o" [out] "-MMD -MF" [m] [i] >> In the expression: >> do { let c = dropDirectory1 $ out -<.> "cxx"; >> let m = out -<.> "m"; >> let i = cmd "pkg-config glib-2.0 --cflags"; >> () <- cmd "c++ -c" [c] "-o" [out] "-MMD -MF" [m] [i]; >> .... } >> In the second argument of `(%>)', namely >> `\ out >> -> do { let ...; >> let ...; >> .... }' >> >> I would appreciate any help in getting the output of the call to >> pkg-config into the compiler invocation. >> >> Thanks, >> Roger >> _______________________________________________ >> Beginners mailing list >> Beginners at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners From rmason at mun.ca Sat Jul 8 11:57:01 2017 From: rmason at mun.ca (Roger Mason) Date: Sat, 08 Jul 2017 09:27:01 -0230 Subject: [Haskell-beginners] using Shake to compile c++ In-Reply-To: (David McBride's message of "Sat, 8 Jul 2017 07:38:24 -0400") References: Message-ID: David McBride writes: > Sorry that should have been command, not command_ which is very different. > > On Sat, Jul 8, 2017 at 7:37 AM, David McBride wrote: >> The easy option is to just use command instead of cmd. Variadic >> functions are always a little weird to type check. >> >> command_ [] "pkg-config" ["glib-2.0","--cflags"] >> >> That will *probably* solve the ambiguity in both lines, but I haven't tested. Thank you for your replies. This is what I have now: "objects//*.o" %> \out -> do let c = dropDirectory1 $ out -<.> "cxx" let m = out -<.> "m" let i = command [] "pkg-config" ["glib-2.0","--cflags"] () <- cmd "c++ -c" [c] "-o" [out] "-MMD -MF" [m] [i] needMakefileDependencies m That produces: Build.hs:29:17: error: * Ambiguous type variable `r0' arising from a use of `command' prevents the constraint `(CmdResult r0)' from being solved. Relevant bindings include i :: Action r0 (bound at Build.hs:29:13) Probable fix: use a type annotation to specify what `r0' should be. These potential instances exist: instance CmdResult CmdLine -- Defined in `Development.Shake.Command' instance CmdResult CmdTime -- Defined in `Development.Shake.Command' instance CmdResult Exit -- Defined in `Development.Shake.Command' ...plus 9 others ...plus two instances involving out-of-scope types (use -fprint-potential-instances to see them all) * In the expression: command [] "pkg-config" ["glib-2.0", "--cflags"] In an equation for `i': i = command [] "pkg-config" ["glib-2.0", "--cflags"] In the expression: do { let c = dropDirectory1 $ out -<.> "cxx"; let m = out -<.> "m"; let i = command ... "pkg-config" ...; () <- cmd "c++ -c" [c] "-o" [out] "-MMD -MF" [m] [i]; .... } Build.hs:30:15: error: * No instance for (Development.Shake.Command.Arg [Action r0]) arising from a use of `cmd' * In a stmt of a 'do' block: () <- cmd "c++ -c" [c] "-o" [out] "-MMD -MF" [m] [i] In the expression: do { let c = dropDirectory1 $ out -<.> "cxx"; let m = out -<.> "m"; let i = command ... "pkg-config" ...; () <- cmd "c++ -c" [c] "-o" [out] "-MMD -MF" [m] [i]; .... } In the second argument of `(%>)', namely `\ out -> do { let ...; let ...; .... }' Thanks again, Roger From toad3k at gmail.com Sat Jul 8 12:51:09 2017 From: toad3k at gmail.com (David McBride) Date: Sat, 8 Jul 2017 08:51:09 -0400 Subject: [Haskell-beginners] Fwd: using Shake to compile c++ In-Reply-To: References: Message-ID: Sorry this should have been sent to the list. ---------- Forwarded message ---------- From: David McBride Date: Sat, Jul 8, 2017 at 8:49 AM Subject: Re: [Haskell-beginners] using Shake to compile c++ To: Roger Mason There's three errors here. pkg-config is an IO action and thus in order to use its output, you must use <- instead of a let binding. Then you must choose what you want to save from that command. You could get the exit result, stderr or stdout or both stdout and stderr. We want stdout. And lastly, Stdout is parameterized over a type a, and you have to decide which. You can either do the following Stdout i <- cmd "pkg-config glib-2.0 --cflags" () <- cmd "c++ -c" [c] "-o" [out] "-MMD -MF" [m] [i :: String] Or you can enable ScopedTypeVariables and go Stdout (i :: String) <- cmd "pkg-config glib-2.0 --cflags" I don't really understand why Stdout is parameterized, rather than just being forced to be a string like Stdin, that's a question for the shake authors. On Sat, Jul 8, 2017 at 7:57 AM, Roger Mason wrote: > David McBride writes: > >> Sorry that should have been command, not command_ which is very different. >> >> On Sat, Jul 8, 2017 at 7:37 AM, David McBride wrote: >>> The easy option is to just use command instead of cmd. Variadic >>> functions are always a little weird to type check. >>> >>> command_ [] "pkg-config" ["glib-2.0","--cflags"] >>> >>> That will *probably* solve the ambiguity in both lines, but I haven't tested. > > Thank you for your replies. > > This is what I have now: > > "objects//*.o" %> \out -> do > let c = dropDirectory1 $ out -<.> "cxx" > let m = out -<.> "m" > let i = command [] "pkg-config" ["glib-2.0","--cflags"] > () <- cmd "c++ -c" [c] "-o" [out] "-MMD -MF" [m] [i] > needMakefileDependencies m > > That produces: > > Build.hs:29:17: error: > * Ambiguous type variable `r0' arising from a use of `command' > prevents the constraint `(CmdResult r0)' from being solved. > Relevant bindings include i :: Action r0 (bound at Build.hs:29:13) > Probable fix: use a type annotation to specify what `r0' should be. > These potential instances exist: > instance CmdResult CmdLine > -- Defined in `Development.Shake.Command' > instance CmdResult CmdTime > -- Defined in `Development.Shake.Command' > instance CmdResult Exit -- Defined in `Development.Shake.Command' > ...plus 9 others > ...plus two instances involving out-of-scope types > (use -fprint-potential-instances to see them all) > * In the expression: > command [] "pkg-config" ["glib-2.0", "--cflags"] > In an equation for `i': > i = command [] "pkg-config" ["glib-2.0", "--cflags"] > In the expression: > do { let c = dropDirectory1 $ out -<.> "cxx"; > let m = out -<.> "m"; > let i = command ... "pkg-config" ...; > () <- cmd "c++ -c" [c] "-o" [out] "-MMD -MF" [m] [i]; > .... } > > Build.hs:30:15: error: > * No instance for (Development.Shake.Command.Arg [Action r0]) > arising from a use of `cmd' > * In a stmt of a 'do' block: > () <- cmd "c++ -c" [c] "-o" [out] "-MMD -MF" [m] [i] > In the expression: > do { let c = dropDirectory1 $ out -<.> "cxx"; > let m = out -<.> "m"; > let i = command ... "pkg-config" ...; > () <- cmd "c++ -c" [c] "-o" [out] "-MMD -MF" [m] [i]; > .... } > In the second argument of `(%>)', namely > `\ out > -> do { let ...; > let ...; > .... }' > > Thanks again, > Roger From rmason at mun.ca Sat Jul 8 14:51:58 2017 From: rmason at mun.ca (Roger Mason) Date: Sat, 08 Jul 2017 12:21:58 -0230 Subject: [Haskell-beginners] Fwd: using Shake to compile c++ In-Reply-To: (David McBride's message of "Sat, 8 Jul 2017 08:51:09 -0400") References: Message-ID: David McBride writes: > Sorry this should have been sent to the list. > > ---------- Forwarded message ---------- > From: David McBride > Date: Sat, Jul 8, 2017 at 8:49 AM > Subject: Re: [Haskell-beginners] using Shake to compile c++ > To: Roger Mason > > > There's three errors here. pkg-config is an IO action and thus in > order to use its output, you must use <- instead of a let binding. > Then you must choose what you want to save from that command. You > could get the exit result, stderr or stdout or both stdout and stderr. > We want stdout. And lastly, Stdout is parameterized over a type a, > and you have to decide which. > > You can either do the following > > Stdout i <- cmd "pkg-config glib-2.0 --cflags" > () <- cmd "c++ -c" [c] "-o" [out] "-MMD -MF" [m] [i :: String] > > Or you can enable ScopedTypeVariables and go > Stdout (i :: String) <- cmd "pkg-config glib-2.0 --cflags" > > I don't really understand why Stdout is parameterized, rather than > just being forced to be a string like Stdin, that's a question for the > shake authors. For the record, I have currently "objects//*.o" %> \out -> do let c = dropDirectory1 $ out -<.> "cxx" let m = out -<.> "m" Stdout i <- cmd "pkg-config glib-2.0 --cflags" need i () <- cmd "c++ -c" [c] "-o" [out] "-MMD -MF" [m] [i :: String] needMakefileDependencies m and get Build.hs:31:59: error: * Couldn't match type `[Char]' with `Char' Expected type: String Actual type: [FilePath] * In the expression: i :: String In the 7th argument of `cmd', namely `[i :: String]' In a stmt of a 'do' block: () <- cmd "c++ -c" [c] "-o" [out] "-MMD -MF" [m] [i :: String] I thank you very much for your help but it is clear that the use of Shake requires rather more Haskell knowledge than is implied by the docs. Given that this is just the easy part of the build the prospects for early success look scant so I will move on and try something else. Thanks again, Roger From apoorv.ingle at gmail.com Tue Jul 11 21:26:04 2017 From: apoorv.ingle at gmail.com (Apoorv Ingle) Date: Tue, 11 Jul 2017 14:26:04 -0700 Subject: [Haskell-beginners] Custom partition lists into groups by providing group sizes using foldl Message-ID: <29C80A07-E2E0-40B8-AF0F-C157555B3519@gmail.com> Hi, I am trying to write a partition function where we pass group sizes and the list we want to partition into groups as arguments and get back a list of groups (or list of lists in this case). My first attempt was by using an auxiliary inner function {-# LANGUAGE ScopedTypeVariables #-} module Partition where partition :: [Int] -> [a] -> [[a]] partition ds ps = reverse $ paux ds ps [] where paux :: [Int] -> [a] -> [[a]] -> [[a]] paux [] [] ps' = ps' paux [] ps ps' = [ps] ++ ps’ paux _ [] ps' = ps' paux (d:ds') ps ps' = paux ds' (snd (splitAt d ps)) ([fst (splitAt d ps)] ++ ps') —————— *Partition> partition [2, 3] [1,2,3,4,5] [[1,2],[3,4,5]] *Partition> partition [1, 2] [1,2,3,4,5] [[1],[2,3],[4,5]] *Partition> partition [1, 2, 5] [1,2,3,4,5] [[1],[2,3],[4,5]] I was speculating if we could write the same function using foldl function but haven’t been able to figure it out. I would really appreciate if you can give me pointers on how we can implement it. partition' :: [Int] -> [a] -> [[a]] partition' [] ds = [ds] partition' ps ds = foldl ??? ???' ???'' contrary to my speculation is it even possible to write such a function using foldl if so why not? Regards, Apoorv Ingle Graduate Student, Computer Science apoorv.ingle at ku.edu -------------- next part -------------- An HTML attachment was scrubbed... URL: From davidmringo at gmail.com Tue Jul 11 22:40:04 2017 From: davidmringo at gmail.com (David Ringo) Date: Tue, 11 Jul 2017 22:40:04 +0000 Subject: [Haskell-beginners] Custom partition lists into groups by providing group sizes using foldl In-Reply-To: <29C80A07-E2E0-40B8-AF0F-C157555B3519@gmail.com> References: <29C80A07-E2E0-40B8-AF0F-C157555B3519@gmail.com> Message-ID: Hi Apoorv, There is indeed a left fold: foldlpart :: [Int] -> [a] -> [[a]] foldlpart ds ps = result where result | null remaining = initial | otherwise = initial ++ [remaining] (initial, remaining) = foldl aux ([], ps) ds aux (l, xs) d = case xs of [] -> (l, xs) _ -> let (f,s) = splitAt d xs in (l ++ [f], s) I'm sure someone else can put something better together though. I much prefer this right fold, since it avoids quadratic behavior incurred with (++) above: foldrpart :: [Int] -> [a] -> [[a]] foldrpart ds ps = myFunc ps where myFunc = foldr buildMyFunc (: []) ds buildMyFunc digit func = \ps -> case ps of [] -> [] _ -> let (first, last) = splitAt digit ps in first : func last If it's unclear, buildMyFunc is basically composing a bunch of functions which know (from the fold on the list of Ints) how many elements to take from some list. Hope this is useful. - David On Tue, Jul 11, 2017 at 3:30 PM Apoorv Ingle wrote: > Hi, > > I am trying to write a partition function where we pass group sizes and > the list we want to partition into groups > as arguments and get back a list of groups (or list of lists in this > case). My first attempt was by using an auxiliary inner function > > {-# LANGUAGE ScopedTypeVariables #-} > > module Partition where > > partition :: [Int] -> [a] -> [[a]] > partition ds ps = reverse $ paux ds ps [] > where > paux :: [Int] -> [a] -> [[a]] -> [[a]] > paux [] [] ps' = ps' > paux [] ps ps' = [ps] ++ ps’ > paux _ [] ps' = ps' > paux (d:ds') ps ps' = paux ds' (snd (splitAt d ps)) ([fst (splitAt d > ps)] ++ ps') > > —————— > > > *Partition> partition [2, 3] [1,2,3,4,5] > [[1,2],[3,4,5]] > *Partition> partition [1, 2] [1,2,3,4,5] > [[1],[2,3],[4,5]] > *Partition> partition [1, 2, 5] [1,2,3,4,5] > [[1],[2,3],[4,5]] > > > > I was speculating if we could write the same function using foldl function > but haven’t been able to figure it out. > I would really appreciate if you can give me pointers on how we can > implement it. > > partition' :: [Int] -> [a] -> [[a]] > partition' [] ds = [ds] > partition' ps ds = foldl ??? ???' ???'' > > > contrary to my speculation is it even possible to write such a function > using foldl if so why not? > > Regards, > Apoorv Ingle > Graduate Student, Computer Science > apoorv.ingle at ku.edu > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: From apoorv.ingle at gmail.com Tue Jul 11 23:18:53 2017 From: apoorv.ingle at gmail.com (Apoorv Ingle) Date: Tue, 11 Jul 2017 16:18:53 -0700 Subject: [Haskell-beginners] Custom partition lists into groups by providing group sizes using foldl In-Reply-To: References: <29C80A07-E2E0-40B8-AF0F-C157555B3519@gmail.com> Message-ID: <219DEFED-7988-472D-90D9-68B74FA4AE21@gmail.com> Hi David, Thanks a lot for the code! foldr is indeed elegant. In general is it advisable to use auxiliary functions or foldr/foldl variations. Does it have any performance benefits or ghc would generate same core language for both the functions? Regards, Apoorv > On Jul 11, 2017, at 15:40, David Ringo wrote: > > Hi Apoorv, > > There is indeed a left fold: > > foldlpart :: [Int] -> [a] -> [[a]] > foldlpart ds ps = result > where result | null remaining = initial > | otherwise = initial ++ [remaining] > (initial, remaining) = foldl aux ([], ps) ds > aux (l, xs) d = case xs of > [] -> (l, xs) > _ -> let (f,s) = splitAt d xs in (l ++ [f], s) > > I'm sure someone else can put something better together though. > > I much prefer this right fold, since it avoids quadratic behavior incurred with (++) above: > > foldrpart :: [Int] -> [a] -> [[a]] > foldrpart ds ps = myFunc ps > where myFunc = foldr buildMyFunc (: []) ds > buildMyFunc digit func = \ps -> > case ps of > [] -> [] > _ -> let (first, last) = splitAt digit ps > in first : func last > > If it's unclear, buildMyFunc is basically composing a bunch of functions which know (from the fold on the list of Ints) how many elements > to take from some list. > > Hope this is useful. > > - David > > On Tue, Jul 11, 2017 at 3:30 PM Apoorv Ingle > wrote: > Hi, > > I am trying to write a partition function where we pass group sizes and the list we want to partition into groups > as arguments and get back a list of groups (or list of lists in this case). My first attempt was by using an auxiliary inner function > > {-# LANGUAGE ScopedTypeVariables #-} > > module Partition where > > partition :: [Int] -> [a] -> [[a]] > partition ds ps = reverse $ paux ds ps [] > where > paux :: [Int] -> [a] -> [[a]] -> [[a]] > paux [] [] ps' = ps' > paux [] ps ps' = [ps] ++ ps’ > paux _ [] ps' = ps' > paux (d:ds') ps ps' = paux ds' (snd (splitAt d ps)) ([fst (splitAt d ps)] ++ ps') > > —————— > > *Partition> partition [2, 3] [1,2,3,4,5] > [[1,2],[3,4,5]] > *Partition> partition [1, 2] [1,2,3,4,5] > [[1],[2,3],[4,5]] > *Partition> partition [1, 2, 5] [1,2,3,4,5] > [[1],[2,3],[4,5]] > > > I was speculating if we could write the same function using foldl function but haven’t been able to figure it out. > I would really appreciate if you can give me pointers on how we can implement it. > > partition' :: [Int] -> [a] -> [[a]] > partition' [] ds = [ds] > partition' ps ds = foldl ??? ???' ???'' > > contrary to my speculation is it even possible to write such a function using foldl if so why not? > > Regards, > Apoorv Ingle > Graduate Student, Computer Science > apoorv.ingle at ku.edu _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners -------------- next part -------------- An HTML attachment was scrubbed... URL: From davidmringo at gmail.com Wed Jul 12 02:02:55 2017 From: davidmringo at gmail.com (David Ringo) Date: Wed, 12 Jul 2017 02:02:55 +0000 Subject: [Haskell-beginners] Custom partition lists into groups by providing group sizes using foldl In-Reply-To: <219DEFED-7988-472D-90D9-68B74FA4AE21@gmail.com> References: <29C80A07-E2E0-40B8-AF0F-C157555B3519@gmail.com> <219DEFED-7988-472D-90D9-68B74FA4AE21@gmail.com> Message-ID: I know that there are specialization rules for foldl and foldr (among other higher-order functions in the Prelude) with the idea that they will produce usually better generated code. So, yes, the generated Core will almost certainly be different. Whether the code is truly more performant (in time or space) will likely depend on your use case. Inspecting the Core manually may give you some insights, but unless you're experienced in that domain, you'll get more direct and faster answers by using GHC's profiling tools with some chosen benchmarks. - David On Tue, Jul 11, 2017 at 5:20 PM Apoorv Ingle wrote: > Hi David, > > Thanks a lot for the code! > > foldr is indeed elegant. > In general is it advisable to use auxiliary functions or foldr/foldl > variations. > Does it have any performance benefits or ghc would generate same core > language for both the functions? > > Regards, > Apoorv > > On Jul 11, 2017, at 15:40, David Ringo wrote: > > Hi Apoorv, > > There is indeed a left fold: > > foldlpart :: [Int] -> [a] -> [[a]] > foldlpart ds ps = result > where result | null remaining = initial > | otherwise = initial ++ [remaining] > (initial, remaining) = foldl aux ([], ps) ds > aux (l, xs) d = case xs of > [] -> (l, xs) > _ -> let (f,s) = splitAt d xs in (l ++ [f], s) > > I'm sure someone else can put something better together though. > > I much prefer this right fold, since it avoids quadratic behavior incurred > with (++) above: > > foldrpart :: [Int] -> [a] -> [[a]] > foldrpart ds ps = myFunc ps > where myFunc = foldr buildMyFunc (: []) ds > buildMyFunc digit func = \ps -> > case ps of > [] -> [] > _ -> let (first, last) = splitAt digit ps > in first : func last > > If it's unclear, buildMyFunc is basically composing a bunch of functions > which know (from the fold on the list of Ints) how many elements > to take from some list. > > Hope this is useful. > > - David > > On Tue, Jul 11, 2017 at 3:30 PM Apoorv Ingle > wrote: > >> Hi, >> >> I am trying to write a partition function where we pass group sizes and >> the list we want to partition into groups >> as arguments and get back a list of groups (or list of lists in this >> case). My first attempt was by using an auxiliary inner function >> >> {-# LANGUAGE ScopedTypeVariables #-} >> >> module Partition where >> >> partition :: [Int] -> [a] -> [[a]] >> partition ds ps = reverse $ paux ds ps [] >> where >> paux :: [Int] -> [a] -> [[a]] -> [[a]] >> paux [] [] ps' = ps' >> paux [] ps ps' = [ps] ++ ps’ >> paux _ [] ps' = ps' >> paux (d:ds') ps ps' = paux ds' (snd (splitAt d ps)) ([fst (splitAt d >> ps)] ++ ps') >> >> —————— >> >> >> *Partition> partition [2, 3] [1,2,3,4,5] >> [[1,2],[3,4,5]] >> *Partition> partition [1, 2] [1,2,3,4,5] >> [[1],[2,3],[4,5]] >> *Partition> partition [1, 2, 5] [1,2,3,4,5] >> [[1],[2,3],[4,5]] >> >> >> >> I was speculating if we could write the same function using foldl >> function but haven’t been able to figure it out. >> I would really appreciate if you can give me pointers on how we can >> implement it. >> >> partition' :: [Int] -> [a] -> [[a]] >> partition' [] ds = [ds] >> partition' ps ds = foldl ??? ???' ???'' >> >> >> contrary to my speculation is it even possible to write such a function >> using foldl if so why not? >> >> Regards, >> Apoorv Ingle >> Graduate Student, Computer Science >> apoorv.ingle at ku.edu >> _______________________________________________ >> Beginners mailing list >> Beginners at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners >> > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: From aquagnu at gmail.com Thu Jul 13 08:29:56 2017 From: aquagnu at gmail.com (Baa) Date: Thu, 13 Jul 2017 11:29:56 +0300 Subject: [Haskell-beginners] How works this `do` example? Message-ID: <20170713112956.15426e6c@Pavel> Hello, Dear List! Consider, I have: request1 :: A -> Connection -> IO () request2 :: A -> Connection -> IO A How does it work - resp <- getConnection >>= do request1 myA request2 anotherA ?! It is compiled but seems that does not execute `request1`... `request1 myA` gets `Connection` value, good. But it does not return `IO Connection`! It returns `IO ()`. But how does `request2 anotherA` get `Connection` value too? Because this is not compiled sure: resp <- getConnection >>= request1 myA >>= request2 anotherA I tried this: module Main where f1 :: Int -> IO () f1 i = do print "f1!" print i return () f2 :: Int -> IO Int f2 i = do print "f2!" print i return i f0 :: IO Int f0 = pure 10 main :: IO () main = f0 >>= do f1 f2 >> print "end" and I get output: "f2!" 10 "end" which means that `f1` is not executing in `do..`-block, but how does `f2` get 10 as input?! == Cheers, Paul From fa-ml at ariis.it Thu Jul 13 09:06:13 2017 From: fa-ml at ariis.it (Francesco Ariis) Date: Thu, 13 Jul 2017 11:06:13 +0200 Subject: [Haskell-beginners] How works this `do` example? In-Reply-To: <20170713112956.15426e6c@Pavel> References: <20170713112956.15426e6c@Pavel> Message-ID: <20170713090613.gx7nqemp5xylnaph@x60s.casa> On Thu, Jul 13, 2017 at 11:29:56AM +0300, Baa wrote: > main :: IO () > main = f0 > >>= do f1 > f2 > >> print "end" > > and I get output: > > "f2!" > 10 > "end" Hello Paul, your `main` desugars to main = f0 >>= (f1 >> f2) >> print "end" Now, the quizzical part is λ> :t (f1 >> f2) (f1 >> f2) :: Int -> IO Int Why does this even type checks? Because: λ> :i (->) [..] instance Monad ((->) r) -- Defined in ‘GHC.Base’ [..] ((->) r) is an instance of Monad! The instance is: instance Monad ((->) r) where f >>= k = \r -> k (f r) r you already know that `m >> k` is defined as `m >>= \_ -> k`, so f >> k = \r -> (\_ -> k) (f r) r = \r -> k r Is it clear enough? From aquagnu at gmail.com Thu Jul 13 09:41:49 2017 From: aquagnu at gmail.com (Baa) Date: Thu, 13 Jul 2017 12:41:49 +0300 Subject: [Haskell-beginners] How works this `do` example? In-Reply-To: <20170713090613.gx7nqemp5xylnaph@x60s.casa> References: <20170713112956.15426e6c@Pavel> <20170713090613.gx7nqemp5xylnaph@x60s.casa> Message-ID: <20170713124149.069163e2@Pavel> I suspected that it was in Read monad, but I don't see where is it this "Read" monad here :) Francesco, thank you very much!! Absolutely clear :) В Thu, 13 Jul 2017 11:06:13 +0200 Francesco Ariis wrote: > On Thu, Jul 13, 2017 at 11:29:56AM +0300, Baa wrote: > > main :: IO () > > main = f0 > > >>= do f1 > > f2 > > >> print "end" > > > > and I get output: > > > > "f2!" > > 10 > > "end" > > Hello Paul, your `main` desugars to > > main = f0 >>= (f1 >> f2) >> print "end" > > Now, the quizzical part is > > λ> :t (f1 >> f2) > (f1 >> f2) :: Int -> IO Int > > Why does this even type checks? Because: > > λ> :i (->) > [..] > instance Monad ((->) r) -- Defined in ‘GHC.Base’ > [..] > > ((->) r) is an instance of Monad! The instance is: > > instance Monad ((->) r) where > f >>= k = \r -> k (f r) r > > you already know that `m >> k` is defined as `m >>= \_ -> k`, so > > f >> k = \r -> (\_ -> k) (f r) r > = \r -> k r > > Is it clear enough? > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners From jeffbrown.the at gmail.com Tue Jul 18 04:10:18 2017 From: jeffbrown.the at gmail.com (Jeffrey Brown) Date: Mon, 17 Jul 2017 21:10:18 -0700 Subject: [Haskell-beginners] How to make this more functional? Message-ID: I wrote a 10-line program[1] for converting from org-mode format to smsn-mode format. Both formats use indentation to indicate hierarchy. In org, a line at level k (levels are positive integers) starts with k asterisks, followed by a space, followed by the text of the line. In smsn-mode, a line at level k starts with 4*(k-1) spaces, followed by an asterisks, followed by a space. I feel like there ought to be an intermediate step where it converts the data to something other than string -- for instance, data IndentedLine = IndentedLine Int String | BadLine and then generates the output from that. It feels like it needs a parser. But when I resurrect my parser code that I understood many moons ago, it looks like a lot of machinery. Thanks. [1] https://github.com/synchrony/smsn-mode/blob/develop/org-to-smsn-mode.hs -- Jeff Brown | Jeffrey Benjamin Brown Website | Facebook | LinkedIn (spammy, so I often miss messages here) | Github -------------- next part -------------- An HTML attachment was scrubbed... URL: From raabe at froglogic.com Tue Jul 18 06:32:15 2017 From: raabe at froglogic.com (Frerich Raabe) Date: Tue, 18 Jul 2017 08:32:15 +0200 Subject: [Haskell-beginners] How to make this more functional? In-Reply-To: References: Message-ID: On 2017-07-18 06:10, Jeffrey Brown wrote: > I wrote a 10-line program[1] for converting from org-mode format to > smsn-mode format. Both formats use indentation to indicate hierarchy. In > org, a line at level k (levels are positive integers) starts with k > asterisks, followed by a space, followed by the text of the line. In > smsn-mode, a line at level k starts with 4*(k-1) spaces, followed by an > asterisks, followed by a space. > > I feel like there ought to be an intermediate step where it converts the > data to something other than string -- for instance, > > data IndentedLine = IndentedLine Int String | BadLine > > and then generates the output from that. I think generating an intermediate data structure makes a lot of sense. To make your program more 'functional', I'd start by factoring out the IO part as early as often. I.e. consider your program to be a function of type 'String -> String': it consumes a string, and yields a string: reformat :: String -> String Now, reformatting the input means splitting it into lines, converting each line, and then merging the lines into a single string again, i.e. we can define 'reformat' as: reformat input = unlines (convertLine (lines input)) To make this type-check, clearly you need some functions with the types lines :: String -> [String] convertLine :: String -> String unlines :: [String] -> String As it happens, the first and the last function are part of the standard library, so we only need to worry about 'convertLine'. Converting a line means parsing the input line and the serialising the parsed data to the output format, i.e. convertLine line = serialiseToOutput (parseLine line) At this point, some sort of data structure to pass from parseLine to serialiseToOutput would be useful. You could certainly go for the 'IndentedLine' type you sketched, i.e. the parseLine function can be declared to be of type parseLine :: String -> IndentedLine I'll skip defining this function, but it might be that the 'span' function defined in the Data.List module might be useful here. With that at hand, you only need to define the serialiseToOutput function which (in order to make this program type-check) needs to be of type serialiseToOutput :: IndentedLine -> String Again, I'll omit the definition here (but the 'replicate' function would probably be useful). At this point, you should have your 'reformat' function fully defined and usable from within 'ghci', i.e. you can nicely test it with some manual input. What's missing is to use it in a real program - you could of course plug it into your existing program calling 'readFile', but as a last idea I'd like to mention the standard 'interact' function which, given a function of type 'String -> String', yields an IO action which reads some input from stdin, applies the given function to it, and then prints the output to stdout. A useful helper for defining UNIX-style filter programs. I believe one lesson to take from this is to not think about how the program does something ('count the number of * characters, etc.) but rather think about _what_ the program does - in this case, in a top-down fashion. Also, in Haskell, this type-driven development works quite nicely to yield programs which you can tinker with very early on. -- Frerich Raabe - raabe at froglogic.com www.froglogic.com - Multi-Platform GUI Testing From raabe at froglogic.com Tue Jul 18 06:33:25 2017 From: raabe at froglogic.com (Frerich Raabe) Date: Tue, 18 Jul 2017 08:33:25 +0200 Subject: [Haskell-beginners] How to make this more functional? In-Reply-To: References: Message-ID: <894a3bdaf18ff091a57ebf9ed4c392cc@froglogic.com> On 2017-07-18 06:10, Jeffrey Brown wrote: > I wrote a 10-line program[1] for converting from org-mode format to > smsn-mode format. Both formats use indentation to indicate hierarchy. In > org, a line at level k (levels are positive integers) starts with k > asterisks, followed by a space, followed by the text of the line. In > smsn-mode, a line at level k starts with 4*(k-1) spaces, followed by an > asterisks, followed by a space. > > I feel like there ought to be an intermediate step where it converts the > data to something other than string -- for instance, > > data IndentedLine = IndentedLine Int String | BadLine > > and then generates the output from that. I think generating an intermediate data structure makes a lot of sense. To make your program more 'functional', I'd start by factoring out the IO part as early as often. I.e. consider your program to be a function of type 'String -> String': it consumes a string, and yields a string: reformat :: String -> String Now, reformatting the input means splitting it into lines, converting each line, and then merging the lines into a single string again, i.e. we can define 'reformat' as: reformat input = unlines (convertLine (lines input)) To make this type-check, clearly you need some functions with the types lines :: String -> [String] convertLine :: String -> String unlines :: [String] -> String As it happens, the first and the last function are part of the standard library, so we only need to worry about 'convertLine'. Converting a line means parsing the input line and the serialising the parsed data to the output format, i.e. convertLine line = serialiseToOutput (parseLine line) At this point, some sort of data structure to pass from parseLine to serialiseToOutput would be useful. You could certainly go for the 'IndentedLine' type you sketched, i.e. the parseLine function can be declared to be of type parseLine :: String -> IndentedLine I'll skip defining this function, but it might be that the 'span' function defined in the Data.List module might be useful here. With that at hand, you only need to define the serialiseToOutput function which (in order to make this program type-check) needs to be of type serialiseToOutput :: IndentedLine -> String Again, I'll omit the definition here (but the 'replicate' function would probably be useful). At this point, you should have your 'reformat' function fully defined and usable from within 'ghci', i.e. you can nicely test it with some manual input. What's missing is to use it in a real program - you could of course plug it into your existing program calling 'readFile', but as a last idea I'd like to mention the standard 'interact' function which, given a function of type 'String -> String', yields an IO action which reads some input from stdin, applies the given function to it, and then prints the output to stdout. A useful helper for defining UNIX-style filter programs. I believe one lesson to take from this is to not think about how the program does something ('count the number of * characters, etc.) but rather think about _what_ the program does - in this case, in a top-down fashion. Also, in Haskell, this type-driven development works quite nicely to yield programs which you can tinker with very early on. -- Frerich Raabe - raabe at froglogic.com www.froglogic.com - Multi-Platform GUI Testing From jeffbrown.the at gmail.com Tue Jul 18 08:43:31 2017 From: jeffbrown.the at gmail.com (Jeffrey Brown) Date: Tue, 18 Jul 2017 01:43:31 -0700 Subject: [Haskell-beginners] How to make this more functional? In-Reply-To: References: Message-ID: interact is slick! And I love that there's a word for unlines. Thanks, Frerich! On Mon, Jul 17, 2017 at 11:32 PM, Frerich Raabe wrote: > On 2017-07-18 06:10, Jeffrey Brown wrote: > >> I wrote a 10-line program[1] for converting from org-mode format to >> smsn-mode format. Both formats use indentation to indicate hierarchy. In >> org, a line at level k (levels are positive integers) starts with k >> asterisks, followed by a space, followed by the text of the line. In >> smsn-mode, a line at level k starts with 4*(k-1) spaces, followed by an >> asterisks, followed by a space. >> >> I feel like there ought to be an intermediate step where it converts the >> data to something other than string -- for instance, >> >> data IndentedLine = IndentedLine Int String | BadLine >> >> and then generates the output from that. >> > > I think generating an intermediate data structure makes a lot of sense. > > To make your program more 'functional', I'd start by factoring out the IO > part as early as often. I.e. consider your program to be a function of type > 'String -> String': it consumes a string, and yields a string: > > reformat :: String -> String > > Now, reformatting the input means splitting it into lines, converting each > line, and then merging the lines into a single string again, i.e. we can > define 'reformat' as: > > reformat input = unlines (convertLine (lines input)) > > To make this type-check, clearly you need some functions with the types > > lines :: String -> [String] > convertLine :: String -> String > unlines :: [String] -> String > > As it happens, the first and the last function are part of the standard > library, so we only need to worry about 'convertLine'. Converting a line > means parsing the input line and the serialising the parsed data to the > output format, i.e. > > convertLine line = serialiseToOutput (parseLine line) > > At this point, some sort of data structure to pass from parseLine to > serialiseToOutput would be useful. You could certainly go for the > 'IndentedLine' type you sketched, i.e. the parseLine function can be > declared to be of type > > parseLine :: String -> IndentedLine > > I'll skip defining this function, but it might be that the 'span' function > defined in the Data.List module might be useful here. With that at hand, > you only need to define the serialiseToOutput function which (in order to > make this program type-check) needs to be of type > > serialiseToOutput :: IndentedLine -> String > > Again, I'll omit the definition here (but the 'replicate' function would > probably be useful). > > At this point, you should have your 'reformat' function fully defined and > usable from within 'ghci', i.e. you can nicely test it with some manual > input. What's missing is to use it in a real program - you could of course > plug it into your existing program calling 'readFile', but as a last idea > I'd like to mention the standard 'interact' function which, given a > function of type 'String -> String', yields an IO action which reads some > input from stdin, applies the given function to it, and then prints the > output to stdout. A useful helper for defining UNIX-style filter programs. > > I believe one lesson to take from this is to not think about how the > program does something ('count the number of * characters, etc.) but rather > think about _what_ the program does - in this case, in a top-down fashion. > Also, in Haskell, this type-driven development works quite nicely to yield > programs which you can tinker with very early on. > > -- > Frerich Raabe - raabe at froglogic.com > www.froglogic.com - Multi-Platform GUI Testing > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > -- Jeff Brown | Jeffrey Benjamin Brown Website | Facebook | LinkedIn (spammy, so I often miss messages here) | Github -------------- next part -------------- An HTML attachment was scrubbed... URL: From aquagnu at gmail.com Mon Jul 24 11:58:31 2017 From: aquagnu at gmail.com (Baa) Date: Mon, 24 Jul 2017 14:58:31 +0300 Subject: [Haskell-beginners] I can't turn-off conreate warning Message-ID: <20170724145831.318f6378@Pavel> Hello, Dear List! I want to turn-off concreate warning (but to have all other, and possible to treat them as errors). This warning is about orphans instances. I tried: -Wall -Werror -Wno-warn-orphans also -Wall -Werror -Wno-warn-warn-orphans But GHC does not understand this option. How to achieve this? -- Best regards, Paul From sylvain at haskus.fr Mon Jul 24 12:03:29 2017 From: sylvain at haskus.fr (Sylvain Henry) Date: Mon, 24 Jul 2017 14:03:29 +0200 Subject: [Haskell-beginners] I can't turn-off conreate warning In-Reply-To: <20170724145831.318f6378@Pavel> References: <20170724145831.318f6378@Pavel> Message-ID: <7d4e4639-9c90-41ad-f7b7-a25931ad46d8@haskus.fr> Hi, Maybe with -Wno-orphans https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/using-warnings.html?#ghc-flag--Worphans Regards, Sylvain On 24/07/2017 13:58, Baa wrote: > Hello, Dear List! > > I want to turn-off concreate warning (but to have all other, and > possible to treat them as errors). This warning is about orphans > instances. I tried: > > -Wall -Werror -Wno-warn-orphans > > also > > -Wall -Werror -Wno-warn-warn-orphans > > But GHC does not understand this option. How to achieve this? > > > -- > Best regards, Paul > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners From aquagnu at gmail.com Mon Jul 24 12:24:57 2017 From: aquagnu at gmail.com (Baa) Date: Mon, 24 Jul 2017 15:24:57 +0300 Subject: [Haskell-beginners] I can't turn-off conreate warning In-Reply-To: <7d4e4639-9c90-41ad-f7b7-a25931ad46d8@haskus.fr> References: <20170724145831.318f6378@Pavel> <7d4e4639-9c90-41ad-f7b7-a25931ad46d8@haskus.fr> Message-ID: <20170724152457.5fc6a30c@Pavel> Ohh, pardon :) My error: seems that `-fno-warn-orphans` works. Not -W but -f :-) > Hi, > > Maybe with -Wno-orphans > > https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/using-warnings.html?#ghc-flag--Worphans > > Regards, > Sylvain > > > On 24/07/2017 13:58, Baa wrote: > > Hello, Dear List! > > > > I want to turn-off concreate warning (but to have all other, and > > possible to treat them as errors). This warning is about orphans > > instances. I tried: > > > > -Wall -Werror -Wno-warn-orphans > > > > also > > > > -Wall -Werror -Wno-warn-warn-orphans > > > > But GHC does not understand this option. How to achieve this? > > > > > > -- > > Best regards, Paul > > _______________________________________________ > > Beginners mailing list > > Beginners at haskell.org > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners From sylvain at haskus.fr Mon Jul 24 13:50:06 2017 From: sylvain at haskus.fr (Sylvain Henry) Date: Mon, 24 Jul 2017 15:50:06 +0200 Subject: [Haskell-beginners] I can't turn-off conreate warning In-Reply-To: <20170724152457.5fc6a30c@Pavel> References: <20170724145831.318f6378@Pavel> <7d4e4639-9c90-41ad-f7b7-a25931ad46d8@haskus.fr> <20170724152457.5fc6a30c@Pavel> Message-ID: <597c55b1-ffed-3d1f-21c4-1260eeb21c83@haskus.fr> Quoting the manual: > To turn off any warning, simply give the corresponding -Wno-... option on the command line. For backwards compatibility with GHC versions prior to 8.0, all these warnings can still be controlled with -f(no-)warn-* instead of -W(no-)*. On 24/07/2017 14:24, Baa wrote: > Ohh, pardon :) > My error: seems that `-fno-warn-orphans` works. Not -W but -f :-) > > >> Hi, >> >> Maybe with -Wno-orphans >> >> https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/using-warnings.html?#ghc-flag--Worphans >> >> Regards, >> Sylvain >> >> >> On 24/07/2017 13:58, Baa wrote: >>> Hello, Dear List! >>> >>> I want to turn-off concreate warning (but to have all other, and >>> possible to treat them as errors). This warning is about orphans >>> instances. I tried: >>> >>> -Wall -Werror -Wno-warn-orphans >>> >>> also >>> >>> -Wall -Werror -Wno-warn-warn-orphans >>> >>> But GHC does not understand this option. How to achieve this? >>> >>> >>> -- >>> Best regards, Paul >>> _______________________________________________ >>> Beginners mailing list >>> Beginners at haskell.org >>> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners >> _______________________________________________ >> Beginners mailing list >> Beginners at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners From aquagnu at gmail.com Tue Jul 25 08:36:11 2017 From: aquagnu at gmail.com (Baa) Date: Tue, 25 Jul 2017 11:36:11 +0300 Subject: [Haskell-beginners] Count with Writer asynchronously Message-ID: <20170725113611.12b050aa@Pavel> Hello, Dear List! There is package `async` (https://hackage.haskell.org/package/async-2.1.1.1/docs/Control-Concurrent-Async.html). Before, I had: import qualified Control.Concurent.Async as A ... runIt :: ... -> IO () ... sequence [A.async $ runIt ...] >>= mapM_ A.wait But now I want to count something inside `runIt`. I will use `Writer` monad for it (sure, it can be `State` also, not in principle to me). To do it synchronously, I done: module Main where import Control.Monad.Trans.Writer import Control.Monad.IO.Class import Data.Monoid runIt :: (Show a, Num a) => WriterT (Sum a) IO () -> a -> WriterT (Sum a) IO () runIt w x = do censor (+1) w -- emulates conditional count of something liftIO $ print x main = do let l = [1,2,3,4] w = writer ((), 0) :: WriterT (Sum Int) IO () z <- runWriterT $ sequence [runIt w i | i <- l] print $ snd z but now my `runIt` changes it's signature: runIt :: Num a => WriterT (Sum a) IO () -> ... -> WriterT (Sum a) IO () ... sequence [A.async $ runIt ...] >>= mapM_ A.wait ^^^^^^^^^^^ ` ERROR is here! I get the error because `async`::IO () -> IO (A.Async ()) but I'm trying to pass it `WriterT (Sum a) IO ()`! To fix it I added `runWriterT` there: res <- sequence [A.async $ runWriterT (runIt ...) ...] >>= mapM A.wait but now I will get list of counters, not one (res::[((), Sum Int)])! How to solve this problem: to run several actions asyncronously and to count something inside the action with `Writer` monad? === Best regards, Paul From michael at snoyman.com Tue Jul 25 09:31:56 2017 From: michael at snoyman.com (Michael Snoyman) Date: Tue, 25 Jul 2017 12:31:56 +0300 Subject: [Haskell-beginners] Count with Writer asynchronously In-Reply-To: <20170725113611.12b050aa@Pavel> References: <20170725113611.12b050aa@Pavel> Message-ID: Firstly, a direct answer to your question: use mconcat. main :: IO () main = do let l = [1,2,3,4] w = writer ((), 0) :: WriterT (Sum Int) IO () z <- sequence (map (A.async . runWriterT . runIt w) l) >>= mapM A.wait print $ snd $ mconcat z Under the surface, WriterT is using mappend to combine the `Sum` values anyway, so it's natural is `mconcat` (the version of mappend that applies to list) to get the same result. Now some possible improvements. You're not actually using the return value from the `runIt` call, just the writer value. There's a function called `execWriter` for this: z <- sequence (map (A.async . execWriterT . runIt w) l) >>= mapM A.wait print $ mconcat z Next, the combination of map and sequence can be written as traverse: z <- traverse (A.async . execWriterT . runIt w) l >>= mapM A.wait But the async library is cool enough that it provides a function called mapConcurrently that deals with the async/wait dance for you: main :: IO () main = do let l = [1,2,3,4] w = writer ((), 0) :: WriterT (Sum Int) IO () z <- A.mapConcurrently (execWriterT . runIt w) l print $ mconcat z One final note: usage of `print` like this in a concurrent context can run into interleaved output if you have the wrong buffer mode turned out, leading to output like this: 2 3 41 This is especially common when using runghc or ghci. You can either change the buffering mode or use a different output function like sayShow (from the say package, which I wrote): module Main where import qualified Control.Concurrent.Async as A import Control.Monad.Trans.Writer import Data.Monoid import Say runIt :: (Show a, Num a) => WriterT (Sum a) IO () -> a -> WriterT (Sum a) IO () runIt w x = do censor (+1) w -- emulates conditional count of something sayShow x main :: IO () main = do let l = [1,2,3,4] w = writer ((), 0) :: WriterT (Sum Int) IO () z <- A.mapConcurrently (execWriterT . runIt w) l sayShow $ mconcat z On Tue, Jul 25, 2017 at 11:36 AM, Baa wrote: > Hello, Dear List! > > There is package `async` > (https://hackage.haskell.org/package/async-2.1.1.1/docs/ > Control-Concurrent-Async.html). > > Before, I had: > > import qualified Control.Concurent.Async as A > ... > runIt :: ... -> IO () > ... > sequence [A.async $ runIt ...] >>= mapM_ A.wait > > But now I want to count something inside `runIt`. I will use > `Writer` monad for it (sure, it can be `State` also, not in > principle to me). To do it synchronously, I done: > > module Main where > > import Control.Monad.Trans.Writer > import Control.Monad.IO.Class > import Data.Monoid > > runIt :: (Show a, Num a) => WriterT (Sum a) IO () -> a -> WriterT (Sum > a) IO () > runIt w x = do > censor (+1) w -- emulates conditional count of something > liftIO $ print x > > main = do > let l = [1,2,3,4] > w = writer ((), 0) :: WriterT (Sum Int) IO () > z <- runWriterT $ sequence [runIt w i | i <- l] > print $ snd z > > but now my `runIt` changes it's signature: > > runIt :: Num a => WriterT (Sum a) IO () -> ... -> WriterT (Sum a) IO () > ... > sequence [A.async $ runIt ...] >>= mapM_ A.wait > ^^^^^^^^^^^ > ` ERROR is here! > > I get the error because `async`::IO () -> IO (A.Async ()) but I'm > trying to pass it `WriterT (Sum a) IO ()`! > > To fix it I added `runWriterT` there: > > res <- sequence [A.async $ runWriterT (runIt ...) ...] >>= mapM A.wait > > but now I will get list of counters, not one (res::[((), Sum Int)])! > > How to solve this problem: to run several actions asyncronously and to > count something > inside the action with `Writer` monad? > > > === > Best regards, Paul > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: From aquagnu at gmail.com Tue Jul 25 10:29:04 2017 From: aquagnu at gmail.com (Baa) Date: Tue, 25 Jul 2017 13:29:04 +0300 Subject: [Haskell-beginners] Count with Writer asynchronously In-Reply-To: References: <20170725113611.12b050aa@Pavel> Message-ID: <20170725132904.43b84b3e@Pavel> Hello, Michael! This answers to my question completely, thank you so much! But looking at this code, I thought: how is it right to wrap/unwrap write monad? In languages like C or Python we can pass input/output argument (`int*` in C or `[0]` in Python) and use it as some accumulator. But here writer monad is not using as accumulator, accumulating (summation) happens in `mconcat`, right? It's using only as output value, i.e. place to "yield" result. I mean `w` is 0, each call of `runIt` sets there 1, after all calls we calculate sum of this 1's. And instead of `censor (+1) w` I can do `tell 1` only. It means that `runIt` can return not `IO ()` but `IO Int` and results of all `runIt`'s asynchnronously gotten values can be accumulated with `mconcat` without using of writer monad. Am I right, writer monad here is not accumulator but only output value (like output arguments in C/C++/IDL/etc)? How is this a typical solution in Haskell - to use writer monad with wrap/unwrap multiple times, only to save output value? On Tue, 25 Jul 2017 12:31:56 +0300 Michael Snoyman wrote: > Firstly, a direct answer to your question: use mconcat. > > main :: IO () > main = do > let l = [1,2,3,4] > w = writer ((), 0) :: WriterT (Sum Int) IO () > z <- sequence > (map (A.async . runWriterT . runIt w) l) > >>= mapM A.wait > print $ snd $ mconcat z > > Under the surface, WriterT is using mappend to combine the `Sum` > values anyway, so it's natural is `mconcat` (the version of mappend > that applies to list) to get the same result. Now some possible > improvements. > > You're not actually using the return value from the `runIt` call, > just the writer value. There's a function called `execWriter` for > this: > > z <- sequence > (map (A.async . execWriterT . runIt w) l) > >>= mapM A.wait > print $ mconcat z > > Next, the combination of map and sequence can be written as traverse: > > z <- traverse (A.async . execWriterT . runIt w) l > >>= mapM A.wait > > But the async library is cool enough that it provides a function > called mapConcurrently that deals with the async/wait dance for you: > > main :: IO () > main = do > let l = [1,2,3,4] > w = writer ((), 0) :: WriterT (Sum Int) IO () > z <- A.mapConcurrently (execWriterT . runIt w) l > print $ mconcat z > > One final note: usage of `print` like this in a concurrent context > can run into interleaved output if you have the wrong buffer mode > turned out, leading to output like this: > > 2 > 3 > 41 > > This is especially common when using runghc or ghci. You can either > change the buffering mode or use a different output function like > sayShow (from the say package, which I wrote): > > module Main where > > import qualified Control.Concurrent.Async as A > import Control.Monad.Trans.Writer > import Data.Monoid > import Say > > runIt :: (Show a, Num a) > => WriterT (Sum a) IO () > -> a > -> WriterT (Sum a) IO () > runIt w x = do > censor (+1) w -- emulates conditional count of something > sayShow x > > main :: IO () > main = do > let l = [1,2,3,4] > w = writer ((), 0) :: WriterT (Sum Int) IO () > z <- A.mapConcurrently (execWriterT . runIt w) l > sayShow $ mconcat z > > > On Tue, Jul 25, 2017 at 11:36 AM, Baa wrote: > > > Hello, Dear List! > > > > There is package `async` > > (https://hackage.haskell.org/package/async-2.1.1.1/docs/ > > Control-Concurrent-Async.html). > > > > Before, I had: > > > > import qualified Control.Concurent.Async as A > > ... > > runIt :: ... -> IO () > > ... > > sequence [A.async $ runIt ...] >>= mapM_ A.wait > > > > But now I want to count something inside `runIt`. I will use > > `Writer` monad for it (sure, it can be `State` also, not in > > principle to me). To do it synchronously, I done: > > > > module Main where > > > > import Control.Monad.Trans.Writer > > import Control.Monad.IO.Class > > import Data.Monoid > > > > runIt :: (Show a, Num a) => WriterT (Sum a) IO () -> a -> > > WriterT (Sum a) IO () > > runIt w x = do > > censor (+1) w -- emulates conditional count of something > > liftIO $ print x > > > > main = do > > let l = [1,2,3,4] > > w = writer ((), 0) :: WriterT (Sum Int) IO () > > z <- runWriterT $ sequence [runIt w i | i <- l] > > print $ snd z > > > > but now my `runIt` changes it's signature: > > > > runIt :: Num a => WriterT (Sum a) IO () -> ... -> WriterT (Sum > > a) IO () ... > > sequence [A.async $ runIt ...] >>= mapM_ A.wait > > ^^^^^^^^^^^ > > ` ERROR is here! > > > > I get the error because `async`::IO () -> IO (A.Async ()) but I'm > > trying to pass it `WriterT (Sum a) IO ()`! > > > > To fix it I added `runWriterT` there: > > > > res <- sequence [A.async $ runWriterT (runIt ...) ...] >>= mapM > > A.wait > > > > but now I will get list of counters, not one (res::[((), Sum Int)])! > > > > How to solve this problem: to run several actions asyncronously and > > to count something > > inside the action with `Writer` monad? > > > > > > === > > Best regards, Paul > > _______________________________________________ > > Beginners mailing list > > Beginners at haskell.org > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > From michael at snoyman.com Tue Jul 25 10:41:35 2017 From: michael at snoyman.com (Michael Snoyman) Date: Tue, 25 Jul 2017 13:41:35 +0300 Subject: [Haskell-beginners] Count with Writer asynchronously In-Reply-To: <20170725132904.43b84b3e@Pavel> References: <20170725113611.12b050aa@Pavel> <20170725132904.43b84b3e@Pavel> Message-ID: You're asking very good questions, about a topic I considered bringing up in my previous response but didn't. I guess I will now :) The important thing to realize about monad transformers (and monads in general) is that _they're nothing special_. Under the surface, WriterT is simply: * Modifying your functions to have an extra value returned * Providing convenience functions like `tell` and `liftIO` to work with that extra value I would strongly advise getting used to writing code in both the transformer and non-transformer style to convince yourself that they are the same thing. To make this concrete, look at the WriterT definition: newtype WriterT w m a = WriterT { runWriterT :: m (a, w) } If you take away the newtype wrapping business, you can see that it's just saying `WriterT w m a = m (a, w)`. And therefore, if we go back to your types, we can replace: WriterT (Sum a) IO () with IO ((), Sum a) In fact, that's exactly what `runWriterT` is doing. I would recommend trying to rewrite your code to not even bother with the `WriterT` at all and see if you can get the same output. So your intuition is correct: there's no output parameter like in C. You could simulate that in Haskell by passing in a mutable variable (like an IORef), but that's not idiomatic. Passing back pairs of values is common in Haskell. Transformers can be useful for avoiding a lot of boilerplate code. They can also introduce a lot of complexity in some cases. Figuring out when is the right time to use them and when not is subjective and nuanced. Knowing the skill is great; being able to avoid using the skill is also important :) On Tue, Jul 25, 2017 at 1:29 PM, Baa wrote: > Hello, Michael! This answers to my question completely, thank you so > much! > > But looking at this code, I thought: how is it right to wrap/unwrap > write monad? In languages like C or Python we can pass input/output > argument (`int*` in C or `[0]` in Python) and use it as some > accumulator. But here writer monad is not using as accumulator, > accumulating (summation) happens in `mconcat`, right? It's using only > as output value, i.e. place to "yield" result. I mean `w` is 0, each > call of `runIt` sets there 1, after all calls we calculate sum of this > 1's. And instead of `censor (+1) w` I can do `tell 1` only. > > It means that `runIt` can return not `IO ()` but `IO Int` and results > of all `runIt`'s asynchnronously gotten values can be accumulated with > `mconcat` without using of writer monad. Am I right, writer monad here > is not accumulator but only output value (like output arguments in > C/C++/IDL/etc)? How is this a typical solution in Haskell - to use > writer monad with wrap/unwrap multiple times, only to save output > value? > > > > On Tue, 25 Jul 2017 12:31:56 +0300 > Michael Snoyman wrote: > > > Firstly, a direct answer to your question: use mconcat. > > > > main :: IO () > > main = do > > let l = [1,2,3,4] > > w = writer ((), 0) :: WriterT (Sum Int) IO () > > z <- sequence > > (map (A.async . runWriterT . runIt w) l) > > >>= mapM A.wait > > print $ snd $ mconcat z > > > > Under the surface, WriterT is using mappend to combine the `Sum` > > values anyway, so it's natural is `mconcat` (the version of mappend > > that applies to list) to get the same result. Now some possible > > improvements. > > > > You're not actually using the return value from the `runIt` call, > > just the writer value. There's a function called `execWriter` for > > this: > > > > z <- sequence > > (map (A.async . execWriterT . runIt w) l) > > >>= mapM A.wait > > print $ mconcat z > > > > Next, the combination of map and sequence can be written as traverse: > > > > z <- traverse (A.async . execWriterT . runIt w) l > > >>= mapM A.wait > > > > But the async library is cool enough that it provides a function > > called mapConcurrently that deals with the async/wait dance for you: > > > > main :: IO () > > main = do > > let l = [1,2,3,4] > > w = writer ((), 0) :: WriterT (Sum Int) IO () > > z <- A.mapConcurrently (execWriterT . runIt w) l > > print $ mconcat z > > > > One final note: usage of `print` like this in a concurrent context > > can run into interleaved output if you have the wrong buffer mode > > turned out, leading to output like this: > > > > 2 > > 3 > > 41 > > > > This is especially common when using runghc or ghci. You can either > > change the buffering mode or use a different output function like > > sayShow (from the say package, which I wrote): > > > > module Main where > > > > import qualified Control.Concurrent.Async as A > > import Control.Monad.Trans.Writer > > import Data.Monoid > > import Say > > > > runIt :: (Show a, Num a) > > => WriterT (Sum a) IO () > > -> a > > -> WriterT (Sum a) IO () > > runIt w x = do > > censor (+1) w -- emulates conditional count of something > > sayShow x > > > > main :: IO () > > main = do > > let l = [1,2,3,4] > > w = writer ((), 0) :: WriterT (Sum Int) IO () > > z <- A.mapConcurrently (execWriterT . runIt w) l > > sayShow $ mconcat z > > > > > > On Tue, Jul 25, 2017 at 11:36 AM, Baa wrote: > > > > > Hello, Dear List! > > > > > > There is package `async` > > > (https://hackage.haskell.org/package/async-2.1.1.1/docs/ > > > Control-Concurrent-Async.html). > > > > > > Before, I had: > > > > > > import qualified Control.Concurent.Async as A > > > ... > > > runIt :: ... -> IO () > > > ... > > > sequence [A.async $ runIt ...] >>= mapM_ A.wait > > > > > > But now I want to count something inside `runIt`. I will use > > > `Writer` monad for it (sure, it can be `State` also, not in > > > principle to me). To do it synchronously, I done: > > > > > > module Main where > > > > > > import Control.Monad.Trans.Writer > > > import Control.Monad.IO.Class > > > import Data.Monoid > > > > > > runIt :: (Show a, Num a) => WriterT (Sum a) IO () -> a -> > > > WriterT (Sum a) IO () > > > runIt w x = do > > > censor (+1) w -- emulates conditional count of something > > > liftIO $ print x > > > > > > main = do > > > let l = [1,2,3,4] > > > w = writer ((), 0) :: WriterT (Sum Int) IO () > > > z <- runWriterT $ sequence [runIt w i | i <- l] > > > print $ snd z > > > > > > but now my `runIt` changes it's signature: > > > > > > runIt :: Num a => WriterT (Sum a) IO () -> ... -> WriterT (Sum > > > a) IO () ... > > > sequence [A.async $ runIt ...] >>= mapM_ A.wait > > > ^^^^^^^^^^^ > > > ` ERROR is here! > > > > > > I get the error because `async`::IO () -> IO (A.Async ()) but I'm > > > trying to pass it `WriterT (Sum a) IO ()`! > > > > > > To fix it I added `runWriterT` there: > > > > > > res <- sequence [A.async $ runWriterT (runIt ...) ...] >>= mapM > > > A.wait > > > > > > but now I will get list of counters, not one (res::[((), Sum Int)])! > > > > > > How to solve this problem: to run several actions asyncronously and > > > to count something > > > inside the action with `Writer` monad? > > > > > > > > > === > > > Best regards, Paul > > > _______________________________________________ > > > Beginners mailing list > > > Beginners at haskell.org > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > > > > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: From aquagnu at gmail.com Tue Jul 25 11:00:10 2017 From: aquagnu at gmail.com (Baa) Date: Tue, 25 Jul 2017 14:00:10 +0300 Subject: [Haskell-beginners] Count with Writer asynchronously In-Reply-To: References: <20170725113611.12b050aa@Pavel> <20170725132904.43b84b3e@Pavel> Message-ID: <20170725140010.77fd5da2@Pavel> Yes, it's true. I see now. Thank you again for that good explanation! On Tue, 25 Jul 2017 13:41:35 +0300 Michael Snoyman wrote: > You're asking very good questions, about a topic I considered > bringing up in my previous response but didn't. I guess I will now :) > > The important thing to realize about monad transformers (and monads in > general) is that _they're nothing special_. Under the surface, > WriterT is simply: > > * Modifying your functions to have an extra value returned > * Providing convenience functions like `tell` and `liftIO` to work > with that extra value > > I would strongly advise getting used to writing code in both the > transformer and non-transformer style to convince yourself that they > are the same thing. To make this concrete, look at the WriterT > definition: > > newtype WriterT w m a = WriterT { runWriterT :: m (a, w) } > > If you take away the newtype wrapping business, you can see that it's > just saying `WriterT w m a = m (a, w)`. And therefore, if we go back > to your types, we can replace: > > WriterT (Sum a) IO () > > with > > IO ((), Sum a) > > In fact, that's exactly what `runWriterT` is doing. I would recommend > trying to rewrite your code to not even bother with the `WriterT` at > all and see if you can get the same output. > > So your intuition is correct: there's no output parameter like in C. > You could simulate that in Haskell by passing in a mutable variable > (like an IORef), but that's not idiomatic. Passing back pairs of > values is common in Haskell. > > Transformers can be useful for avoiding a lot of boilerplate code. > They can also introduce a lot of complexity in some cases. Figuring > out when is the right time to use them and when not is subjective and > nuanced. Knowing the skill is great; being able to avoid using the > skill is also important :) > > On Tue, Jul 25, 2017 at 1:29 PM, Baa wrote: > > > Hello, Michael! This answers to my question completely, thank you so > > much! > > > > But looking at this code, I thought: how is it right to wrap/unwrap > > write monad? In languages like C or Python we can pass input/output > > argument (`int*` in C or `[0]` in Python) and use it as some > > accumulator. But here writer monad is not using as accumulator, > > accumulating (summation) happens in `mconcat`, right? It's using > > only as output value, i.e. place to "yield" result. I mean `w` is > > 0, each call of `runIt` sets there 1, after all calls we calculate > > sum of this 1's. And instead of `censor (+1) w` I can do `tell 1` > > only. > > > > It means that `runIt` can return not `IO ()` but `IO Int` and > > results of all `runIt`'s asynchnronously gotten values can be > > accumulated with `mconcat` without using of writer monad. Am I > > right, writer monad here is not accumulator but only output value > > (like output arguments in C/C++/IDL/etc)? How is this a typical > > solution in Haskell - to use writer monad with wrap/unwrap multiple > > times, only to save output value? > > > > > > > > On Tue, 25 Jul 2017 12:31:56 +0300 > > Michael Snoyman wrote: > > > > > Firstly, a direct answer to your question: use mconcat. > > > > > > main :: IO () > > > main = do > > > let l = [1,2,3,4] > > > w = writer ((), 0) :: WriterT (Sum Int) IO () > > > z <- sequence > > > (map (A.async . runWriterT . runIt w) l) > > > >>= mapM A.wait > > > print $ snd $ mconcat z > > > > > > Under the surface, WriterT is using mappend to combine the `Sum` > > > values anyway, so it's natural is `mconcat` (the version of > > > mappend that applies to list) to get the same result. Now some > > > possible improvements. > > > > > > You're not actually using the return value from the `runIt` call, > > > just the writer value. There's a function called `execWriter` for > > > this: > > > > > > z <- sequence > > > (map (A.async . execWriterT . runIt w) l) > > > >>= mapM A.wait > > > print $ mconcat z > > > > > > Next, the combination of map and sequence can be written as > > > traverse: > > > > > > z <- traverse (A.async . execWriterT . runIt w) l > > > >>= mapM A.wait > > > > > > But the async library is cool enough that it provides a function > > > called mapConcurrently that deals with the async/wait dance for > > > you: > > > > > > main :: IO () > > > main = do > > > let l = [1,2,3,4] > > > w = writer ((), 0) :: WriterT (Sum Int) IO () > > > z <- A.mapConcurrently (execWriterT . runIt w) l > > > print $ mconcat z > > > > > > One final note: usage of `print` like this in a concurrent context > > > can run into interleaved output if you have the wrong buffer mode > > > turned out, leading to output like this: > > > > > > 2 > > > 3 > > > 41 > > > > > > This is especially common when using runghc or ghci. You can > > > either change the buffering mode or use a different output > > > function like sayShow (from the say package, which I wrote): > > > > > > module Main where > > > > > > import qualified Control.Concurrent.Async as A > > > import Control.Monad.Trans.Writer > > > import Data.Monoid > > > import Say > > > > > > runIt :: (Show a, Num a) > > > => WriterT (Sum a) IO () > > > -> a > > > -> WriterT (Sum a) IO () > > > runIt w x = do > > > censor (+1) w -- emulates conditional count of something > > > sayShow x > > > > > > main :: IO () > > > main = do > > > let l = [1,2,3,4] > > > w = writer ((), 0) :: WriterT (Sum Int) IO () > > > z <- A.mapConcurrently (execWriterT . runIt w) l > > > sayShow $ mconcat z > > > > > > > > > On Tue, Jul 25, 2017 at 11:36 AM, Baa wrote: > > > > > > > Hello, Dear List! > > > > > > > > There is package `async` > > > > (https://hackage.haskell.org/package/async-2.1.1.1/docs/ > > > > Control-Concurrent-Async.html). > > > > > > > > Before, I had: > > > > > > > > import qualified Control.Concurent.Async as A > > > > ... > > > > runIt :: ... -> IO () > > > > ... > > > > sequence [A.async $ runIt ...] >>= mapM_ A.wait > > > > > > > > But now I want to count something inside `runIt`. I will use > > > > `Writer` monad for it (sure, it can be `State` also, not in > > > > principle to me). To do it synchronously, I done: > > > > > > > > module Main where > > > > > > > > import Control.Monad.Trans.Writer > > > > import Control.Monad.IO.Class > > > > import Data.Monoid > > > > > > > > runIt :: (Show a, Num a) => WriterT (Sum a) IO () -> a -> > > > > WriterT (Sum a) IO () > > > > runIt w x = do > > > > censor (+1) w -- emulates conditional count of something > > > > liftIO $ print x > > > > > > > > main = do > > > > let l = [1,2,3,4] > > > > w = writer ((), 0) :: WriterT (Sum Int) IO () > > > > z <- runWriterT $ sequence [runIt w i | i <- l] > > > > print $ snd z > > > > > > > > but now my `runIt` changes it's signature: > > > > > > > > runIt :: Num a => WriterT (Sum a) IO () -> ... -> WriterT > > > > (Sum a) IO () ... > > > > sequence [A.async $ runIt ...] >>= mapM_ A.wait > > > > ^^^^^^^^^^^ > > > > ` ERROR is here! > > > > > > > > I get the error because `async`::IO () -> IO (A.Async ()) but > > > > I'm trying to pass it `WriterT (Sum a) IO ()`! > > > > > > > > To fix it I added `runWriterT` there: > > > > > > > > res <- sequence [A.async $ runWriterT (runIt ...) ...] >>= > > > > mapM A.wait > > > > > > > > but now I will get list of counters, not one (res::[((), Sum > > > > Int)])! > > > > > > > > How to solve this problem: to run several actions asyncronously > > > > and to count something > > > > inside the action with `Writer` monad? > > > > > > > > > > > > === > > > > Best regards, Paul > > > > _______________________________________________ > > > > Beginners mailing list > > > > Beginners at haskell.org > > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > > > > > > > _______________________________________________ > > Beginners mailing list > > Beginners at haskell.org > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > From lud.sund at gmail.com Thu Jul 27 06:44:19 2017 From: lud.sund at gmail.com (lud.sund at gmail.com) Date: Thu, 27 Jul 2017 08:44:19 +0200 Subject: [Haskell-beginners] Updates in the ST monad, seems slow Message-ID: <20170727064419.GR2658@keysersoze> Hi all. I'm a Haskell beginner looking for valuable inputs, I don't expect my program to magically fix itself. I've implemented a maximum matching graph algorithm in Haskell. The implementation specification uses some state, some arrays that are indexed and updated throughout the algorithm. At first, I implemented the state using HashMaps. This went well, but the runtime wasn't close to my professors corresponding C program. I profiled my program and found out that adjusting the maps were taking alot of time. Then, I had a look at Data.HashTable.ST.Basic. I thought, getting average constant time lookup and insert would surely fix the problem with the slow state updates. I reimplemented the algorithm using HashTables and ran the program. As it turned out, the runtime didn't decrease using the ST monad, rather increase. And heavily. A program instance that took 100 seconds using maps now took 400 seconds. Looking at a profiling sample, it shows that HashTable lookup and other various procedures related to HashTables are the big time consumers. How can this be possible? Any ideas? The code is available under https://github.com/lsund/edmonds-matching/ where: The 'main' branch is the map implementation, and 'hashtable' branch is the hashtable implementation. The code is quite messy, and since I'm a beginner, probably inefficient. It is the first time I implemented anything using the ST monad. So I'm afraid that I don't understand it perfectly, and made some serious implementation flaw. Best Regards, Ludvig From mike_k_houghton at yahoo.co.uk Thu Jul 27 08:33:33 2017 From: mike_k_houghton at yahoo.co.uk (mike h) Date: Thu, 27 Jul 2017 09:33:33 +0100 Subject: [Haskell-beginners] Streams Message-ID: Hi, I'm looking at this: data Stream a = Cons a (Stream a) and with streamFromSeed :: (a -> a) -> a -> Stream a streamFromSeed f a = Cons a (streamFromSeed f (f a)) I can do, for example, evens :: Stream Integer evens = streamFromSeed (+2) 0 what I'd like to do is take one item at a time from the stream. My first shot was next :: (Stream a) -> (Stream a, a) but that means I need to keep a ref to the stream that is returned in the tuple which makes for messy code for subsequent calls to next. I sense that the State monad needs to be involved but I'm not sure exactly how as my experiments with State still required I keep a ref to the 'new' stream. Conceptually I see this as a 'global' state and next is just next :: a but that's 30 years of imperative programming speaking and is, I think, wrong! Any help would be really appreciated. Thanks Mike From fa-ml at ariis.it Thu Jul 27 10:08:03 2017 From: fa-ml at ariis.it (Francesco Ariis) Date: Thu, 27 Jul 2017 12:08:03 +0200 Subject: [Haskell-beginners] Streams In-Reply-To: References: Message-ID: <20170727100803.u6xwxvpndqfi7jhi@x60s.casa> On Thu, Jul 27, 2017 at 09:33:33AM +0100, mike h wrote: > What I'd like to do is take one item at a time from the stream. My first > shot was > > next :: (Stream a) -> (Stream a, a) > > but that means I need to keep a ref to the stream that is returned in the tuple which makes for messy code > for subsequent calls to next. I sense that the State monad needs to be involved but I'm not sure exactly how as > my experiments with State still required I keep a ref to the 'new' stream. Conceptually I see this as a 'global' state > and next is just > > next :: a > > but that's 30 years of imperative programming speaking and is, I think, > wrong! Hello Mike, I see nothing wrong with a State monad (you signature looks really like the one inside a State monad, after all) next :: Stream a -> (a, Stream a) next' :: s -> (a, s ) Many many many other ways of dealing elegantly with streams have been proposed; check for example this article [1], which starts exactly from your example, e.g. data Stream b = SCons (b, Stream b) And then, if you are sold to the idea, exploring the various libraries on hackage is the other half of the fun :P -F [1] https://blog.jle.im/entry/intro-to-machines-arrows-part-1-stream-and From sylvain at haskus.fr Thu Jul 27 11:08:43 2017 From: sylvain at haskus.fr (Sylvain Henry) Date: Thu, 27 Jul 2017 13:08:43 +0200 Subject: [Haskell-beginners] Updates in the ST monad, seems slow In-Reply-To: <20170727064419.GR2658@keysersoze> References: <20170727064419.GR2658@keysersoze> Message-ID: I don't know why it is slower but since you're using ST you could try with (unboxed) arrays instead of hashmaps: https://hackage.haskell.org/package/array-0.5.1.0/docs/Data-Array-ST.html On 27/07/2017 08:44, lud.sund at gmail.com wrote: > Hi all. I'm a Haskell beginner looking for valuable inputs, I don't expect my program to magically fix itself. > > I've implemented a maximum matching graph algorithm in Haskell. The implementation specification uses some state, some arrays that are indexed and updated throughout the algorithm. > > At first, I implemented the state using HashMaps. This went well, but the runtime wasn't close to my professors corresponding C program. I profiled my program and found out that adjusting the maps were taking alot of time. > > Then, I had a look at Data.HashTable.ST.Basic. I thought, getting average constant time lookup and insert would surely fix the problem with the slow state updates. I reimplemented the algorithm using HashTables and ran the program. > > As it turned out, the runtime didn't decrease using the ST monad, rather increase. And heavily. A program instance that took 100 seconds using maps now took 400 seconds. Looking at a profiling sample, it shows that HashTable lookup and other various procedures related to HashTables are the big time consumers. > > How can this be possible? Any ideas? > > The code is available under https://github.com/lsund/edmonds-matching/ where: > The 'main' branch is the map implementation, and 'hashtable' branch is the hashtable implementation. > > The code is quite messy, and since I'm a beginner, probably inefficient. It is the first time I implemented anything using the ST monad. So I'm afraid that I don't understand it perfectly, and made some serious implementation flaw. > > Best Regards, > Ludvig > > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners From mike_k_houghton at yahoo.co.uk Thu Jul 27 12:29:00 2017 From: mike_k_houghton at yahoo.co.uk (mike h) Date: Thu, 27 Jul 2017 13:29:00 +0100 Subject: [Haskell-beginners] Streams In-Reply-To: <20170727100803.u6xwxvpndqfi7jhi@x60s.casa> References: <20170727100803.u6xwxvpndqfi7jhi@x60s.casa> Message-ID: <852910CF-CF85-46CF-ADBE-294CB9A9908F@yahoo.co.uk> Thanks Francesco - I’ll follow up the link. M > On 27 Jul 2017, at 11:08, Francesco Ariis wrote: > > On Thu, Jul 27, 2017 at 09:33:33AM +0100, mike h wrote: >> What I'd like to do is take one item at a time from the stream. My first >> shot was >> >> next :: (Stream a) -> (Stream a, a) >> >> but that means I need to keep a ref to the stream that is returned in the tuple which makes for messy code >> for subsequent calls to next. I sense that the State monad needs to be involved but I'm not sure exactly how as >> my experiments with State still required I keep a ref to the 'new' stream. Conceptually I see this as a 'global' state >> and next is just >> >> next :: a >> >> but that's 30 years of imperative programming speaking and is, I think, >> wrong! > > Hello Mike, > > I see nothing wrong with a State monad (you signature looks really like > the one inside a State monad, after all) > > next :: Stream a -> (a, Stream a) > next' :: s -> (a, s ) > > Many many many other ways of dealing elegantly with streams have been > proposed; check for example this article [1], which starts exactly > from your example, e.g. > > data Stream b = SCons (b, Stream b) > > And then, if you are sold to the idea, exploring the various libraries > on hackage is the other half of the fun :P > -F > > [1] https://blog.jle.im/entry/intro-to-machines-arrows-part-1-stream-and > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners From atrudyjane at protonmail.com Mon Jul 31 05:09:12 2017 From: atrudyjane at protonmail.com (Atrudyjane) Date: Mon, 31 Jul 2017 01:09:12 -0400 Subject: [Haskell-beginners] Libraries for Playing Audio Message-ID: Hello Cafe, Is there a recommended Haskell library for playing/manipulating audio files? There's a long list of sound libraries on Hackage, and was thinking looking into either conduit-audio or SDL-mixer. Thank You, Andrea Sent with [ProtonMail](https://protonmail.com) Secure Email. -------------- next part -------------- An HTML attachment was scrubbed... URL: From info at maximka.de Mon Jul 31 05:50:23 2017 From: info at maximka.de (info at maximka.de) Date: Mon, 31 Jul 2017 07:50:23 +0200 (CEST) Subject: [Haskell-beginners] Libraries for Playing Audio In-Reply-To: References: Message-ID: <1197554121.73338.1501480223697@communicator.strato.de> There is haskell wrapper for powerful sox availiable also. http://hackage.haskell.org/package/sox Alexei > On 31 July 2017 at 07:09 Atrudyjane wrote: > > > Hello Cafe, > Is there a recommended Haskell library for playing/manipulating audio files? There's a long list of sound libraries on Hackage, and was thinking looking into either conduit-audio or SDL-mixer. > Thank You, > Andrea > > Sent with [ProtonMail](https://protonmail.com) Secure Email._______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners