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