From trent.shipley at gmail.com Mon Sep 3 09:05:32 2018 From: trent.shipley at gmail.com (trent shipley) Date: Mon, 3 Sep 2018 02:05:32 -0700 Subject: [Haskell-beginners] Hutton 2016 ex8.3a Message-ID: Given data Tree a = Leaf a | Node (Tree a) (Tree a) Write a leaf counter. Hutton suggests: leaves :: Tree a -> Int leaves (Leaf _) = 1 leaves (Node l r) = leaves l + leaves r I tried: leavesTrent :: Tree a -> Int leavesTrent = leaves' 0 where leaves' n (Leaf a) = n + 1 leaves' n (Node l r) = (leaves' n l), (leaves' n r) The idea is: If it is a leaf, add one to the accumulator. (Following Hutton's explanation of how sum works if defined with foldl.) If it is a tree, proceed down the left subtree recursively, until you get to a leaf, then roll up to the right subtree. The problem (among the problems) is that I don't know how to tell the compiler to do all lefts, before backing up to go right. I only know how to do that using a real operator like "+" or foo (l, r). Is that kind of no-op recursive branching possible? Trent. -------------- next part -------------- An HTML attachment was scrubbed... URL: From rajasekaran.rishi at gmail.com Mon Sep 3 10:05:44 2018 From: rajasekaran.rishi at gmail.com (Rishi Rajasekaran) Date: Mon, 3 Sep 2018 15:35:44 +0530 Subject: [Haskell-beginners] Hutton 2016 ex8.3a In-Reply-To: References: Message-ID: Hi Trent For executing your approach, you can do the following: 1. Compute the number of leaves in the left subtree first. 2. Pass that computed value into leaves' call for the right subtree Regards Rishi On Mon, 3 Sep, 2018, 2:36 PM trent shipley, wrote: > Given > data Tree a = Leaf a | Node (Tree a) (Tree a) > > Write a leaf counter. > > Hutton suggests: > > leaves :: Tree a -> Int > leaves (Leaf _) = 1 > leaves (Node l r) = leaves l + leaves r > > I tried: > > leavesTrent :: Tree a -> Int > leavesTrent = leaves' 0 > where > leaves' n (Leaf a) = n + 1 > leaves' n (Node l r) = (leaves' n l), (leaves' n r) > > The idea is: > > If it is a leaf, add one to the accumulator. (Following Hutton's > explanation of how sum works if defined with foldl.) If it is a tree, > proceed down the left subtree recursively, until you get to a leaf, then > roll up to the right subtree. The problem (among the problems) is that I > don't know how to tell the compiler to do all lefts, before backing up to > go right. I only know how to do that using a real operator like "+" or foo > (l, r). > > Is that kind of no-op recursive branching possible? > > Trent. > _______________________________________________ > 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 trent.shipley at gmail.com Tue Sep 4 06:00:53 2018 From: trent.shipley at gmail.com (trent shipley) Date: Mon, 3 Sep 2018 23:00:53 -0700 Subject: [Haskell-beginners] Hutton 2016 ex8.3a In-Reply-To: References: Message-ID: data Tree a = Leaf a | Node (Tree a) (Tree a) How could I modify this definition so that a Node could be: Node (Tree a) Null/Nothing/[] -- basically a zilch that would match anything or nothing, because it would make programming simple. Alternatively: Node (Tree a) -- Would I be looking at, data Tree a = Leaf a | Node (Tree a) Maybe (Tree a) -- Or possibly the best I can do is, data Tree a = Leaf a | Node (Tree a) (Tree a) | Node (Tree a) On Mon, Sep 3, 2018 at 3:06 AM Rishi Rajasekaran < rajasekaran.rishi at gmail.com> wrote: > Hi Trent > > For executing your approach, you can do the following: > 1. Compute the number of leaves in the left subtree first. > 2. Pass that computed value into leaves' call for the right subtree > > Regards > > Rishi > > > On Mon, 3 Sep, 2018, 2:36 PM trent shipley, > wrote: > >> Given >> data Tree a = Leaf a | Node (Tree a) (Tree a) >> >> Write a leaf counter. >> >> Hutton suggests: >> >> leaves :: Tree a -> Int >> leaves (Leaf _) = 1 >> leaves (Node l r) = leaves l + leaves r >> >> I tried: >> >> leavesTrent :: Tree a -> Int >> leavesTrent = leaves' 0 >> where >> leaves' n (Leaf a) = n + 1 >> leaves' n (Node l r) = (leaves' n l), (leaves' n r) >> >> The idea is: >> >> If it is a leaf, add one to the accumulator. (Following Hutton's >> explanation of how sum works if defined with foldl.) If it is a tree, >> proceed down the left subtree recursively, until you get to a leaf, then >> roll up to the right subtree. The problem (among the problems) is that I >> don't know how to tell the compiler to do all lefts, before backing up to >> go right. I only know how to do that using a real operator like "+" or foo >> (l, r). >> >> Is that kind of no-op recursive branching possible? >> >> Trent. >> > _______________________________________________ >> 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 trent.shipley at gmail.com Wed Sep 5 09:53:25 2018 From: trent.shipley at gmail.com (trent shipley) Date: Wed, 5 Sep 2018 02:53:25 -0700 Subject: [Haskell-beginners] Alternative ways define trees Message-ID: In which I try a couple of ways to declare alternative trees that can have one or two sub-trees per node, but my attempts don't work. How do I get them to work? Is it preferable to require two trees per node? Regards, Trent Shipley {-- 3. Consider the following type of binary trees: data Tree a = Leaf a | Node (Tree a) (Tree a) Let us say that such a tree is balanced if the number of leaves in the left and right subtree of every node differs by at most one, with leaves themselves being trivially balanced. Define a function balanced :: Tree a -> Bool that decides if a binary tree is balanced or not. Hint: first define a function that returns the number of leaves in a tree. Hutton, Graham. Programming in Haskell (Kindle Locations 3355-3361). Cambridge University Press. Kindle Edition. --} data Tree a = Leaf a | Node (Tree a) (Tree a) -- From Hutton. -- You can't have an empty tree of a node with no branches. A degenerate tree consists of one leaf, when my intuition says a leaf should be required to have a node. A node must have two sub-trees, it can't have one sub-tree. I have mixed feelings about not being able to have a node with one sub-tree. data Tree' a = Leaf' a | Node' (Tree' a) Maybe (Tree' a) -- First failed experiment. -- can this be made with the "data" word, if not what are the options? This is my preferred constructor. A node that can contain two trees, or one tree and "Nothing". {------------------------- ex8_3experiments.hs:20:46: error: • Expecting one more argument to ‘Maybe’ Expected a type, but ‘Maybe’ has kind ‘* -> *’ • In the type ‘Maybe’ In the definition of data constructor ‘Node'’ In the data declaration for ‘Tree'’ Failed, modules loaded: none. ---------------------------} data Tree'' a = Leaf'' a | Node'' (Tree'' a) (Tree'' a) | Node'' (Tree'' a) -- second failed experiment. -- This is an inferior option for this, since your tree walking functions have to worry about a non-existent right path. -- How would I create this? {-------------------------- ex8_3experiments.hs:21:59: error: Multiple declarations of ‘Node''’ Declared at: ex8_3experiments.hs:21:28 ex8_3experiments.hs:21:59 Failed, modules loaded: none. ---------------------------} tEven :: Tree Int tEven = Node (Node (Leaf 1) (Leaf 2)) (Node (Leaf 3) (Leaf 4)) -- Test :: Tree Int -- tTest = Node (Node (Leaf 1) (Leaf 2)) (Node (Leaf 3)) {--------------- To make a "canonical" balanced odd tree you have an odd number of two leaf sub-trees, and one three leaf sub-tree at the end. n / \ / \ n n / \ / \ 1 2 3 n / \ 4 5 ----------------} tOdd :: Tree Int tOdd = Node (Node (Leaf 1) (Leaf 2)) (Node (Leaf 3) (Node (Leaf 4) (Leaf 5))) tUnbal :: Tree Int tUnbal = Node (Node (Leaf 1) (Node (Leaf 2) (Node (Leaf 3) (Leaf 4)))) (Node (Leaf 5) (Leaf 6)) leaves :: Tree a -> Int leaves (Leaf _) = 1 leaves (Node l r) = leaves l + leaves r -- From Hutton's solutions. balanced :: Tree a -> Bool balanced (Leaf _) = True balanced (Node l r) = abs(leaves l - leaves r) <= 1 && balanced l && balanced r -- From Hutton's solutions. -------------- next part -------------- An HTML attachment was scrubbed... URL: From chr.maeder at web.de Wed Sep 5 11:07:36 2018 From: chr.maeder at web.de (C Maeder) Date: Wed, 5 Sep 2018 13:07:36 +0200 Subject: [Haskell-beginners] Alternative ways define trees In-Reply-To: References: Message-ID: Hi Trent Shipley, the most general trees are given in http://hackage.haskell.org/package/containers-0.6.0.1/docs/Data-Tree.html A short version is: data Tree a = Tree a [Tree a] Such a tree can have arbitrarily many sub-trees. A leaf could be defined as: leaf a = Tree a [] Note that any node has a value (in contrast to binary trees). Your failed experiment below could be corrected with additional parentheses: data Tree' a = Leaf' a | Node' (Tree' a) (Maybe (Tree' a)) For all this tree versions there is no notion of something like an empty tree. Adding an extra constructor (like "Empty | ...") has the effect that subtrees may also be empty, which may be not desirable if subtrees should be simply omitted if empty. HTH Christian Am 05.09.2018 um 11:53 schrieb trent shipley: > In which I try a couple of ways to declare alternative trees that can > have one or two sub-trees per node, but my attempts don't work.  How do > I get them to work?  Is it preferable to require two trees per node? > > Regards, > > Trent Shipley > > {-- > > 3. Consider the following type of binary trees: > > data Tree a = Leaf a | Node (Tree a) (Tree a) > > Let us say that such a tree is balanced if the number of leaves in the > left and right subtree of every node differs by at most one, with leaves > themselves being trivially balanced. Define a function > > balanced :: Tree a -> Bool > > that decides if a binary tree is balanced or not. > > Hint: first define a function that returns the number of leaves in a tree. > > Hutton, Graham. Programming in Haskell (Kindle Locations 3355-3361). > Cambridge University Press. Kindle Edition. > > --} > > data Tree a   = Leaf a   | Node   (Tree a)   (Tree a) > > -- From Hutton.   > -- You can't have an empty tree of a node with no branches.  A > degenerate tree consists of one leaf, when my intuition says a leaf > should be required to have a node.  A node must have two sub-trees, it > can't have one sub-tree.  I have mixed feelings about not being able to > have a node with one sub-tree. > > data Tree' a  = Leaf' a  | Node'  (Tree' a)  Maybe (Tree' a) -- First > failed experiment. > > -- can this be made with the "data" word, if not what are the options?  > This is my preferred constructor.  A node that can contain two trees, or > one tree and "Nothing". > > {------------------------- > ex8_3experiments.hs:20:46: error: >     • Expecting one more argument to ‘Maybe’ >       Expected a type, but ‘Maybe’ has kind ‘* -> *’ >     • In the type ‘Maybe’ >       In the definition of data constructor ‘Node'’ >       In the data declaration for ‘Tree'’ > Failed, modules loaded: none. > ---------------------------} > > data Tree'' a = Leaf'' a | Node'' (Tree'' a) (Tree'' a) | Node'' (Tree'' > a) -- second failed experiment. > > -- This is an inferior option for this, since your tree walking > functions have to worry about a non-existent right path. > -- How would I create this? > > {-------------------------- > ex8_3experiments.hs:21:59: error: >     Multiple declarations of ‘Node''’ >     Declared at: ex8_3experiments.hs:21:28 >                  ex8_3experiments.hs:21:59 > Failed, modules loaded: none. > ---------------------------} > > > tEven :: Tree Int > tEven = Node (Node (Leaf 1) (Leaf 2)) >              (Node (Leaf 3) (Leaf 4)) > > -- Test :: Tree Int > -- tTest = Node (Node (Leaf 1) (Leaf 2)) (Node (Leaf 3)) > > {--------------- > To make a "canonical" balanced odd tree you have an odd number of two > leaf sub-trees, and one three leaf sub-tree at the end. > > >       n >      / \ >     /   \ >    n     n >   / \   / \ >  1  2  3   n >           / \ >          4   5 > ----------------} > > tOdd :: Tree Int > tOdd = Node (Node (Leaf 1) (Leaf 2)) >              (Node (Leaf 3) (Node (Leaf 4) (Leaf 5))) > > tUnbal :: Tree Int > tUnbal = Node (Node (Leaf 1) >                (Node (Leaf 2) >                 (Node (Leaf 3) >                  (Leaf 4)))) >                (Node (Leaf 5) (Leaf 6)) > > leaves :: Tree a -> Int > leaves (Leaf _) = 1 > leaves (Node l r) = leaves l + leaves r > > -- From Hutton's solutions. > > balanced :: Tree a -> Bool > balanced (Leaf _) = True > balanced (Node l r) = abs(leaves l - leaves r) <= 1 >                       && balanced l >                       && balanced r > > -- From Hutton's solutions. > > > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > From jaakko.luttinen at iki.fi Sat Sep 8 14:19:13 2018 From: jaakko.luttinen at iki.fi (Jaakko Luttinen) Date: Sat, 8 Sep 2018 17:19:13 +0300 Subject: [Haskell-beginners] Why Integral makes a function much slower than Int? Message-ID: Hi all, I implemented a simple function to calculate the length of a list. However, I noticed that the speed of the function changes significantly if I make I minor change to the type signature but keep the implementation the same otherwise. I was wondering why this happens. Contents of mylength.hs: module MyLength where -- Here is the first implementation: myLength :: Integral n => [a] -> n myLength xs = run xs 0 where run [] n = n run (_:ys) n = run ys (n+1) -- Then, the other implementation just fixes the return type without -- modifying the actual implementation: myLength' :: [a] -> Int myLength' = myLength When I compile these implementations with: ghc -dynamic -O2 mylength.hs Then, launch ghci: ghci -fobject-code And in ghci: :load mylength.hs :set +s (myLength [1..10000000]) :: Int 10000000 (2.30 secs, 1,612,737,944 bytes) (myLength' [1..10000000]) :: Int 10000000 (0.38 secs, 720,077,536 bytes) So, the first implementation is much worse, although I've fixed the return type to Int too. What's going on? Does this mean one shouldn't use Integral but Int instead most of the time? Thanks for help! Regards, Jaakko From trent.shipley at gmail.com Fri Sep 14 08:04:12 2018 From: trent.shipley at gmail.com (trent shipley) Date: Fri, 14 Sep 2018 01:04:12 -0700 Subject: [Haskell-beginners] Hutton Ex 8.9.5 & Ex 8.9.6 Message-ID: Pankaj Godbole's code examples for 8.9.6 are sufficiently more complex than mine,that I am worried I missed an obvious bug I'm not experience enough to know about or test for. Correction or reassurances would be appreciated. Regards, Trent {-- 5. Given the type declaration data Expr = Val Int | Add Expr Expr define a higher-order function folde :: (Int -> a) -> (a -> a -> a) -> Expr -> a such that folde f g replaces each Val constructor in an expression by the function f, and each Add constructor by the function g. Hutton, Graham. Programming in Haskell (Kindle Locations 3364-3371). Cambridge University Press. Kindle Edition. --} data Expr = Val Int | Add Expr Expr -- Trent's stuff folde :: (Int -> a) -> (a -> a -> a) -> Expr -> a folde f g (Val x) = f x folde f g (Add left right) = g (folde f g left) (folde f g right) {-- 6. Using folde, define a function eval :: Expr -> Int that evaluates an expression to an integer value, and a function size :: Expr -> Int that calculates the number of values in an expression. Hutton, Graham. Programming in Haskell (Kindle Locations 3372-3374). Cambridge University Press. Kindle Edition. --} -- Trent's stuff eval :: Expr -> Int eval = folde id (+) size :: Expr -> Int size = folde (\_ -> 1) (+) -- hlint suggests \_ as const 1 test0 :: Expr test0 = Val 1 test1 :: Expr test1 = Add (Val 1) (Val 2) test3 :: Expr test3 = Add (Val 1) (Add (Val 2) (Val 3)) -- the below are from: -- Pankaj Godbole -- https://github.com/pankajgodbole/hutton/blob/master/exercises.hs evalE :: Expr -> Int evalE (Val n) = n evalE (Add e1 e2) = folde toEnum (+) (Add e1 e2) -- doesn't a Val have to prefix an int? Then why is f "toEnum"? numVals :: Expr -> Int numVals (Val n) = 1 numVals (Add e1 e2) = numVals e1 + numVals e2 -------------- next part -------------- An HTML attachment was scrubbed... URL: From toad3k at gmail.com Fri Sep 14 12:06:02 2018 From: toad3k at gmail.com (David McBride) Date: Fri, 14 Sep 2018 08:06:02 -0400 Subject: [Haskell-beginners] Hutton Ex 8.9.5 & Ex 8.9.6 In-Reply-To: References: Message-ID: Your answers are good. toEnum is redundant. Reconstructing the Add is unnecessary. His second function is fine but it doesn't use folde. I would take hlint's suggestion and use const. This situation is a common use case. On Fri, Sep 14, 2018 at 4:04 AM trent shipley wrote: > Pankaj Godbole's code examples for 8.9.6 are sufficiently more complex > than mine,that I am worried I missed an obvious bug I'm not experience > enough to know about or test for. > > Correction or reassurances would be appreciated. > > Regards, > > Trent > > {-- > > 5. Given the type declaration > > data Expr = Val Int | Add Expr Expr > > define a higher-order function > > folde :: (Int -> a) -> (a -> a -> a) -> Expr -> a > > such that folde f g replaces each Val constructor in an expression by the > function f, and each Add constructor by the function g. > > Hutton, Graham. Programming in Haskell (Kindle Locations 3364-3371). > Cambridge University Press. Kindle Edition. > > --} > > data Expr = Val Int | Add Expr Expr > > -- Trent's stuff > > folde :: (Int -> a) -> (a -> a -> a) -> Expr -> a > folde f g (Val x) = f x > folde f g (Add left right) = g (folde f g left) (folde f g right) > > {-- > > 6. Using folde, define a function > > eval :: Expr -> Int > > that evaluates an expression to an integer value, and a function > > size :: Expr -> Int > > that calculates the number of values in an expression. > > Hutton, Graham. Programming in Haskell (Kindle Locations 3372-3374). > Cambridge University Press. Kindle Edition. > > --} > > -- Trent's stuff > > eval :: Expr -> Int > eval = folde id (+) > > size :: Expr -> Int > size = folde (\_ -> 1) (+) -- hlint suggests \_ as const 1 > > test0 :: Expr > test0 = Val 1 > > test1 :: Expr > test1 = Add (Val 1) (Val 2) > > test3 :: Expr > test3 = Add (Val 1) (Add (Val 2) (Val 3)) > > -- the below are from: > -- Pankaj Godbole > -- https://github.com/pankajgodbole/hutton/blob/master/exercises.hs > > evalE :: Expr -> Int > evalE (Val n) = n > evalE (Add e1 e2) = folde toEnum (+) (Add e1 e2) > -- doesn't a Val have to prefix an int? Then why is f "toEnum"? > > > numVals :: Expr -> Int > numVals (Val n) = 1 > numVals (Add e1 e2) = numVals e1 + numVals e2 > _______________________________________________ > 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 trent.shipley at gmail.com Sat Sep 15 08:23:47 2018 From: trent.shipley at gmail.com (trent shipley) Date: Sat, 15 Sep 2018 01:23:47 -0700 Subject: [Haskell-beginners] Hutton Ex 8.9.7 Message-ID: I couldn't get close on my own. From: https://github.com/pankajgodbole/hutton/blob/master/exercises.hs {- 7. Complete the following instance declarations: instance Eq a => Eq (Maybe a) where ... instance Eq a => Eq [a] where ... -} -- suggested answer instance Eq a => Eq (Maybe a) where -- Defines the (==) operation. Nothing == Nothing = True Just == Just = True -- why isn't this Just a == Just a ? -- My guess is that a and Just a are different types and can't be == in Haskell _ == _ = False instance Eq a => Eq [a] where -- Defines the (==) operation. [] == [] = True [x] == [y] = x == y (x:xs) == (y:ys) = x==y && xs==ys -- I assume this is implicitly recursive. _ == _ = False -------------- next part -------------- An HTML attachment was scrubbed... URL: From to_br at uni-bremen.de Sat Sep 15 09:17:54 2018 From: to_br at uni-bremen.de (Tobias Brandt) Date: Sat, 15 Sep 2018 11:17:54 +0200 Subject: [Haskell-beginners] Hutton Ex 8.9.7 In-Reply-To: Message-ID: <20180915111754.Horde.sccVnMTF7yurt8PhLMJ0x3S@webmail.uni-bremen.de> Hey, a few notes: 1. The (==) function in the second equation of the Maybe instance of (==) is not complete yet, since you need to match on instances of the Maybe type and "Just :: a -> Maybe a". Your idea "Just a == Just a" goes in the right direction, but please note that you can't bind two variable names ("a") in the same equation. You need to give each "boxed value" a different name. I'm sure you can work it out from there. 2.  The right hand side of "(x:xs) == (y:ys)" is not implicitly recursive, but rather explicitly! Since we apply the function (==) to the smaller lists "xs" and "ys" until we arrive at a base case.  Greetings, Tobias ----- Nachricht von trent shipley ---------      Datum: Sat, 15 Sep 2018 01:23:47 -0700        Von: trent shipley Antwort an: The Haskell-Beginners Mailing List - Discussion of primarily beginner-level topics related to Haskell    Betreff: [Haskell-beginners] Hutton Ex 8.9.7         An: Haskell Beginners > I couldn't get close on my own.   > From: https://github.com/pankajgodbole/hutton/blob/master/exercises.hs >   > {- > 7. Complete the following instance declarations: >      instance Eq a => Eq (Maybe a) where >      ... >   >      instance Eq a => Eq [a] where >      ... > -} > -- suggested answer >   > instance Eq a => Eq (Maybe a) where >   -- Defines the (==) operation. >   Nothing == Nothing = True >   Just    == Just    = True  >     -- why isn't this Just a == Just a ? >     -- My guess is that a and Just a are different types and > can't be == in            Haskell >   _       == _       = False >   > instance Eq a => Eq [a] where >   -- Defines the (==) operation. >   [] == []         = True >   [x] == [y]       = x == y >   (x:xs) == (y:ys) = x==y && xs==ys -- I assume this is > implicitly recursive. >   _  == _          = False  >   > >   ----- Ende der Nachricht von trent shipley ----- -------------- next part -------------- An HTML attachment was scrubbed... URL: From 50295 at web.de Sun Sep 16 23:16:53 2018 From: 50295 at web.de (Olumide) Date: Mon, 17 Sep 2018 00:16:53 +0100 Subject: [Haskell-beginners] Need better explanation of the 'flipThree' example in LYAH In-Reply-To: <20180821010057.cyu6pg6mdb5fq5ff@x60s.casa> References: <83c66b35-f934-4a09-4274-24585cb0d3bb@web.de> <20180821010057.cyu6pg6mdb5fq5ff@x60s.casa> Message-ID: Hi Francesco, Thanks as always for your reply. (I note that you've replied many of my questions.) I have not replied because I've been thinking very hard about this problem and in particular about the way the do notation is desugared in this case and something doesn't sit right with me. (Obviously there's something I've failed to understand.) Take for example do a <- coin b <- coin return ([a,b]) This would desugar into do a <- coin do b <- coin return [a,b] and ultimately into coin >>= ( \a -> coin >>= ( \b -> return [a,b] )) Noting that m >>= f = flatten (fmap f m) , and recursively applying expanding >>= I get flatten( fmap (\a -> coin >>= ( \b -> return [a,b] ) ) coin ) and flatten( fmap (\a -> ( flatten( fmap ( \b -> return [a,b] ) coin ) ) coin ) Is this how to proceed and how am I to simplify this expression? Regards, - Olumide On 21/08/18 02:00, Francesco Ariis wrote: > Hello Olumide, > > On Tue, Aug 21, 2018 at 01:04:01AM +0100, Olumide wrote: >> My understanding of what's going on here is sketchy at best. One of several >> explanations that I am considering is that all combination of a, b and c are >> evaluated in (==Tails) [a,b,c] but I cannot explain how the all function >> creates 'fuses' the list [f a, f b, f c]. I know that all f xs = and . map f >> xs (the definition on hackage is a lot more complicated) but, again, I >> cannot explain how the and function 'fuses' the list [f a, f b, f c]. > > Let's copy the relevant monad instance: > > instance Monad Prob where > return x = Prob [(x,1%1)] > m >>= f = flatten (fmap f m) > > and desugar `flipThree: > > flipThree = coin >>= \a -> > coin >>= \b -> > loadedCoin >>= \c -> > return (all (==Tails) [a,b,c]) > > > Now it should be clearer: `coin >>= \a -> ...something...` takes `coin` > (Prob [(Heads,1%2),(Tails,1%2)]), applies a function (\a -> ...) to all > of its elements, flattens (probability wise) the result. > So approximately we have: > > 1. some list ([a, b]) > 2. nested lists after applying `\a -> ...` [[a1, a2], [b1, b2]] > 3. some more flattened list [a1, a2, b1, b2] > > `\a -> ...` itself contains `\b ->` which cointains `\c ->`, those are > nested rounds of the same (>>=) trick we saw above. > At each time the intermediate result is bound to a variable (\a, \b > and \c), so for each triplet we can use `all`. > >> If I'm on the right track I realize that I'm going to have to study the list >> the between list comprehensions and the do-notation in order how all the >> return function create one Prob. > > Indeed I recall working the example on paper the first time I read it: > once you do it, it should stick! > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > From fa-ml at ariis.it Mon Sep 17 00:09:18 2018 From: fa-ml at ariis.it (Francesco Ariis) Date: Mon, 17 Sep 2018 02:09:18 +0200 Subject: [Haskell-beginners] Need better explanation of the 'flipThree' example in LYAH In-Reply-To: References: <83c66b35-f934-4a09-4274-24585cb0d3bb@web.de> <20180821010057.cyu6pg6mdb5fq5ff@x60s.casa> Message-ID: <20180917000917.3ymmmfztomlc4gwy@x60s.casa> Hello Olumide, On Mon, Sep 17, 2018 at 12:15:58AM +0100, Sola Aina wrote: > flatten( fmap (\a -> ( flatten( fmap ( \b -> return [a,b] ) coin ) ) coin ) > > Is this how to proceed and how am I to simplify this expression? I get a slightly different final expression: flatten (fmap (\a -> flatten (fmap (\b -> return [a,b]) coin)) coin) -- notice the lack of `(` before the second `flatten` This could be rewritten as: flatMap (\a -> flatMap (\b -> return [a,b]) coin) coin -- flatMap :: (a1 -> Prob a2) -> Prob a1 -> Prob a2 -- flatMap f x = flatten (fmap f x) which is a bit easier on the eyes. This expression cannot be simplified any further if we don't bring to the table the definition of `coin`! From 50295 at web.de Wed Sep 19 10:03:04 2018 From: 50295 at web.de (Olumide) Date: Wed, 19 Sep 2018 11:03:04 +0100 Subject: [Haskell-beginners] Need better explanation of the 'flipThree' example in LYAH In-Reply-To: <20180917000917.3ymmmfztomlc4gwy@x60s.casa> References: <83c66b35-f934-4a09-4274-24585cb0d3bb@web.de> <20180821010057.cyu6pg6mdb5fq5ff@x60s.casa> <20180917000917.3ymmmfztomlc4gwy@x60s.casa> Message-ID: <299b0121-ca10-25a2-a3ec-ee9aefa4de8c@web.de> Thanks Francesco. You are right. I had one too many rbraces. However from the definition fmap f (Prob xs) = Prob $ map (\(x,p) -> (f x , p)) xs and x = Head | Tails suggests to me that f ought to be a function like any (==Heads) that applies to [x] Therefore I've changed the desugared expression to flatten( fmap (\a -> flatten( fmap ( \b -> return ( any (== Heads) [a,b] ) ) coin ) ) coin ) So that from the definition of coin, the inner expression fmap ( \b -> return ( any (== Heads) [a,b] ) ) coin expands to fmap ( \b -> return ( any (== Heads) [a,b] ) ) Prob[ (Heads, 1%2) , (Tails, 1%2) ] Detour: writing all this made me realize that (1) the lambda is applied the lambda to all elements(?) of the Prob, and (2) the term a represents each element of the outer Prob. So that the above expression becomes Prob $ [ (any (==Heads)[a,Head], 1%2) , (any (==Head)[a,Tails], 1%2) ] writing all this made me realize that (1) the lambda is applied to all elements(?) of the Prob, and that (2) the term a represents each element of the outer Prob -- I think I am starting to see the similarity/connection between the do-notation and list comprehensions. Returning to the above expression, when the term a is Heads, we get Prob [ (return any (==Heads)[Heads,Head], 1%2) , (return any (==Head)[Heads,Tails], 1%2) ] and because return any (==Heads)[Heads,Head] = Prob[True,1%1] , and return any (==Heads)[Heads,Tails] = Prob[True,1%1] The above expression becomes Prob [ (Prob[True,1%1] , 1%2 ) , ( Prob[True,1%1] , 1%2 ) ] The double Prob makes it clear why flatten is needed. I'll stop here and wait for your feedback. BTW, I'm considering using GHC.Proof to assert that this sequence of reductions is equivalent. Regards, - Oumide On 17/09/18 01:09, Francesco Ariis wrote: > Hello Olumide, > > On Mon, Sep 17, 2018 at 12:15:58AM +0100, Sola Aina wrote: >> flatten( fmap (\a -> ( flatten( fmap ( \b -> return [a,b] ) coin ) ) coin ) >> >> Is this how to proceed and how am I to simplify this expression? > > I get a slightly different final expression: > > flatten (fmap (\a -> flatten (fmap (\b -> return [a,b]) coin)) coin) > -- notice the lack of `(` before the second `flatten` > > This could be rewritten as: > > flatMap (\a -> flatMap (\b -> return [a,b]) coin) coin > > -- flatMap :: (a1 -> Prob a2) -> Prob a1 -> Prob a2 > -- flatMap f x = flatten (fmap f x) > > which is a bit easier on the eyes. This expression cannot be simplified > any further if we don't bring to the table the definition of `coin`! > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > From frederic-emmanuel.picca at synchrotron-soleil.fr Fri Sep 21 08:25:20 2018 From: frederic-emmanuel.picca at synchrotron-soleil.fr (PICCA Frederic-Emmanuel) Date: Fri, 21 Sep 2018 08:25:20 +0000 Subject: [Haskell-beginners] optimisation of code Message-ID: Hello, I would like to have your advice in order to optimize this code. The purpose is to trigg an action 'a' if a list of files (thousands) exists. A process copy files from one directory to another. allFilesThere :: MonadIO m => [Path Abs File] -> m Bool allFilesThere fs = liftIO $ allM (doesFileExist . fromAbsFile) fs trigOnAllFiles :: MonadIO m => m r -> [Path Abs File] -> m r trigOnAllFiles a fs = go where go = do r <- allFilesThere fs if r then a else ( do liftIO $ threadDelay 1000000 go) It works, but it consums a lot's of resources when all the files does not exists yet. So I would like your advice in order to optimize it :) thanks for your help. Frederic From trent.shipley at gmail.com Fri Sep 21 10:26:02 2018 From: trent.shipley at gmail.com (trent shipley) Date: Fri, 21 Sep 2018 03:26:02 -0700 Subject: [Haskell-beginners] Haskell interpretation of names produces error? Message-ID: data Prop = Const Bool | Var Char | Not Prop | And Prop Prop | If Prop Prop | Or Prop Prop | Yff Prop Prop -- Why do I get errors if "Yff" is replaced with "Iff"? | Xor Prop Prop type Assoc k v = [(k, v)] -- Hutton, Graham. Programming in Haskell (p. 93). Cambridge University Press. Kindle Edition. find :: Eq k => k -> Assoc k v -> v find k t = head [v | (k', v) <- t, k == k'] -- Hutton, Graham. Programming in Haskell (p. 93). Cambridge University Press. Kindle Edition. type Subst = Assoc Char Bool -- Hutton, 2016, Ch 8.6 eval :: Subst -> Prop -> Bool eval _ (Const b) = b eval s (Var x) = find x s eval s (Not p) = not (eval s p) eval s (And p q) = eval s p && eval s q eval s (If p q) = eval s p <= eval s q eval s (Or p q) = eval s p || eval s q eval s (Yff p q) = eval s p == eval s q -- Iff produces error here eval s (Xor p q) = eval s p /= eval s q -- Hutton 2016 Ch 8.6 vars :: Prop -> [Char] vars (Const _) = [] vars (Var x) = [x] vars (Not p) = vars p vars (And p q) = vars p ++ vars q vars (If p q) = vars p ++ vars q vars (Or p q) = vars p ++ vars q vars (Yff p q) = vars p ++ vars q -- Iff produces error here vars (Xor p q) = vars p ++ vars q -- Hutton 2016 Ch 8.6 -------------- next part -------------- An HTML attachment was scrubbed... URL: From fa-ml at ariis.it Fri Sep 21 10:42:23 2018 From: fa-ml at ariis.it (Francesco Ariis) Date: Fri, 21 Sep 2018 12:42:23 +0200 Subject: [Haskell-beginners] Haskell interpretation of names produces error? In-Reply-To: References: Message-ID: <20180921104223.aqjkxwzsvj76bfd3@x60s.casa> Hello trent, On Fri, Sep 21, 2018 at 03:26:02AM -0700, trent shipley wrote: > data Prop = Const Bool > [...] changing all the three occurrences of Yff to Iff does not produce error. If you change only two you will get an error, because you have a pattern-matching against a non-existent constructor -F From juravel2 at gmail.com Fri Sep 21 10:46:16 2018 From: juravel2 at gmail.com (Oleg Nykolyn) Date: Fri, 21 Sep 2018 13:46:16 +0300 Subject: [Haskell-beginners] optimisation of code In-Reply-To: References: Message-ID: Hi, Current code re-checks file existence always in same order, so worst case is - N files and only last of them does not exists. In that case this code will re-check (N-1) files during each consecutive retry. This can be optimized by moving already existing files to the end of file list(or dropping them from list completely, if files are only added but never removed). For this you could re-write `allFilesThere` something like: allFilesThere fs = liftIO $ do existing, non_existing <- partitionM (doesFileExist . fromAbsFile) fs return (non_existing++ existing, null non_existing) Then allFilesThere could start next iteration by checking previously non-existing files and probably failing much faster. On Fri, Sep 21, 2018 at 11:25 AM PICCA Frederic-Emmanuel < frederic-emmanuel.picca at synchrotron-soleil.fr> wrote: > Hello, > > I would like to have your advice in order to optimize this code. > The purpose is to trigg an action 'a' if a list of files (thousands) > exists. > A process copy files from one directory to another. > > allFilesThere :: MonadIO m => [Path Abs File] -> m Bool > allFilesThere fs = liftIO $ allM (doesFileExist . fromAbsFile) fs > > trigOnAllFiles :: MonadIO m => m r -> [Path Abs File] -> m r > trigOnAllFiles a fs = go > where > go = do > r <- allFilesThere fs > if r then a else > ( do liftIO $ threadDelay 1000000 > go) > > It works, but it consums a lot's of resources when all the files does not > exists yet. > So I would like your advice in order to optimize it :) > > thanks for your help. > > Frederic > _______________________________________________ > 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 toad3k at gmail.com Fri Sep 21 11:45:46 2018 From: toad3k at gmail.com (David McBride) Date: Fri, 21 Sep 2018 07:45:46 -0400 Subject: [Haskell-beginners] optimisation of code In-Reply-To: References: Message-ID: My first instinct is to just use anyM instead of allM allFilesThere :: MonadIO m => [Path Abs File] -> m Bool allFilesThere fs = liftIO $ anyM (not . doesFileExist . fromAbsFile) fs However you'll now have the opposite problem. It will take a lot of resources when all the files are there. But maybe that is okay for your use case? On Fri, Sep 21, 2018 at 4:25 AM PICCA Frederic-Emmanuel < frederic-emmanuel.picca at synchrotron-soleil.fr> wrote: > Hello, > > I would like to have your advice in order to optimize this code. > The purpose is to trigg an action 'a' if a list of files (thousands) > exists. > A process copy files from one directory to another. > > allFilesThere :: MonadIO m => [Path Abs File] -> m Bool > allFilesThere fs = liftIO $ allM (doesFileExist . fromAbsFile) fs > > trigOnAllFiles :: MonadIO m => m r -> [Path Abs File] -> m r > trigOnAllFiles a fs = go > where > go = do > r <- allFilesThere fs > if r then a else > ( do liftIO $ threadDelay 1000000 > go) > > It works, but it consums a lot's of resources when all the files does not > exists yet. > So I would like your advice in order to optimize it :) > > thanks for your help. > > Frederic > _______________________________________________ > 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 sumitraja at gmail.com Sat Sep 22 09:40:34 2018 From: sumitraja at gmail.com (Sumit Raja) Date: Sat, 22 Sep 2018 15:10:34 +0530 Subject: [Haskell-beginners] FreeBSD port build 8.4.3_1 - StackOverflowHook Message-ID: Hi, I'm unable to get a consistent build of the FreeBSD 8.4.3 port on a 1.1-RELEASE-p11-amd64. I had success with a one build (in a jail) but am now seeing this problem on a VM: gmake --no-print-directory -f ghc.mk phase=1 phase_1_builds HC [stage 0] ghc/stage1/build/tmp/ghc-stage1 Warning: -rtsopts and -with-rtsopts have no effect with -no-hs-main. Call hs_init_ghc() from your main() function to set these options. /usr/local/lib/ghc-8.4.2/rts/libHSrts.a(RTS.o): In function `StackOverflowHook': /home/ben/bin-dist-8.4.2-FreeBSD/ghc/rts/hooks/StackOverflow.c:16:0: error: multiple definition of `StackOverflowHook' ghc/stage1/build/hschooks.o:hschooks.c:(.text+0x0): first defined here collect2: error: ld returned 1 exit status `gcc7' failed in phase `Linker'. (Exit code: 1) gmake[3]: *** [ghc/ghc.mk:111: ghc/stage1/build/tmp/ghc-stage1] Error 1 Thanks Sumit From rmason at mun.ca Sat Sep 22 11:25:22 2018 From: rmason at mun.ca (Roger Mason) Date: Sat, 22 Sep 2018 08:55:22 -0230 Subject: [Haskell-beginners] FreeBSD port build 8.4.3_1 - StackOverflowHook In-Reply-To: References: Message-ID: Hello, Sumit Raja writes: > I'm unable to get a consistent build of the FreeBSD 8.4.3 port on a > 1.1-RELEASE-p11-amd64. I had success with a one build (in a jail) but > am now seeing this problem on a VM: > > gmake --no-print-directory -f ghc.mk phase=1 phase_1_builds > HC [stage 0] ghc/stage1/build/tmp/ghc-stage1 > Warning: -rtsopts and -with-rtsopts have no effect with -no-hs-main. > Call hs_init_ghc() from your main() function to set these options. > /usr/local/lib/ghc-8.4.2/rts/libHSrts.a(RTS.o): In function `StackOverflowHook': > > /home/ben/bin-dist-8.4.2-FreeBSD/ghc/rts/hooks/StackOverflow.c:16:0: error: > multiple definition of `StackOverflowHook' > ghc/stage1/build/hschooks.o:hschooks.c:(.text+0x0): first defined here > collect2: error: ld returned 1 exit status > `gcc7' failed in phase `Linker'. (Exit code: 1) > gmake[3]: *** [ghc/ghc.mk:111: ghc/stage1/build/tmp/ghc-stage1] Error 1 It isn't clear from your message how you are building ghc. I have ghc-8.4.3 installed from the port on FreeBSD 11.1 and it works without issue. These two lines: > /usr/local/lib/ghc-8.4.2/rts/libHSrts.a(RTS.o): In function `StackOverflowHook': > /home/ben/bin-dist-8.4.2-FreeBSD/ghc/rts/hooks/StackOverflow.c:16:0: error: refer to 8.4.2, which looks a bit fishy to me. Good luck, Roger From sumitraja at gmail.com Sat Sep 29 10:19:24 2018 From: sumitraja at gmail.com (Sumit Raja) Date: Sat, 29 Sep 2018 15:49:24 +0530 Subject: [Haskell-beginners] FreeBSD port build 8.4.3_1 - StackOverflowHook In-Reply-To: References: Message-ID: > From: Roger Mason > It isn't clear from your message how you are building ghc. I have > ghc-8.4.3 installed from the port on FreeBSD 11.1 and it works without > issue. > > These two lines: > > > /usr/local/lib/ghc-8.4.2/rts/libHSrts.a(RTS.o): In function `StackOverflowHook': > > /home/ben/bin-dist-8.4.2-FreeBSD/ghc/rts/hooks/StackOverflow.c:16:0: error: > > refer to 8.4.2, which looks a bit fishy to me. It was a standard port build using portsnap and make && make install. Clean install of the ports tree using a fresh ghc to bootstrap worked correctly - I think the ports tree was very broken. -Sumit From rmason at mun.ca Sat Sep 29 10:42:54 2018 From: rmason at mun.ca (Roger Mason) Date: Sat, 29 Sep 2018 08:12:54 -0230 Subject: [Haskell-beginners] FreeBSD port build 8.4.3_1 - StackOverflowHook In-Reply-To: References: Message-ID: Sumit Raja writes: > > It was a standard port build using portsnap and make && make install. > Clean install of the ports tree using a fresh ghc to bootstrap worked > correctly - I think the ports tree was very broken. Glad to hear you got it fixed. Roger