From twilson at csufresno.edu Thu Aug 1 02:45:05 2019
From: twilson at csufresno.edu (Todd Wilson)
Date: Wed, 31 Jul 2019 19:45:05 0700
Subject: [Haskellcafe] Performance best practices
MessageID:
Dear Cafe:
I'm getting to the point in my Haskell learning curve where I'm
getting more interested in the fine points of programming for
performance and would be grateful for some ideas of the tools and
options available for exploring this. To make this concrete, let me
give a simple example. Here are two different ways of coding the same
listsplitting function:
import Data.List (inits,tails)
splits1, splits2 :: [a] > [([a],[a])]
splits1 xs = zip (inits xs) (tails xs)
splits2 [] = [([],[])]
splits2 xs@(x:xs') = ([],xs) : [(x:as,bs)  (as,bs) < splits2 xs']
For example, splits1 [1,2,3] is
[([],[1,2,3]),([1],[2,3]),([1,2],[3]),([1,2,3],[])].
How do these functions compare in their actual time and space usage?
It seems that, asymptotically, tails is O(n) while inits is O(n^2) in
both time and space (when fully evaluated), and splits2 is also
O(n^2), but how would I go about comparing them in actual usage to get
a more precise comparison? What profiling or runtime statistics could
I gather to make a decision about which one to use in a situation
where performance mattered (assuming for the sake of discussion that
such a situation existed for this simple example)? And, out of
curiosity, is there an even more efficient way to code this function?
Thanks,
Todd Wilson
From jo at durchholz.org Thu Aug 1 05:50:17 2019
From: jo at durchholz.org (Joachim Durchholz)
Date: Thu, 1 Aug 2019 07:50:17 +0200
Subject: [Haskellcafe] ANN: To Kata Haskellen Evangelion
InReplyTo:
References:
<72ad2c39ee1f645684342f06c563e5ca@durchholz.org>
<3ae4443931a1d702a914699593b42621@durchholz.org>
MessageID:
Am 31.07.19 um 22:33 schrieb Vanessa McHale:
> I'm not convinced that nontermination would be worth redesigning the
> language  the research implementations seem rough.
That all implementations are rough does not imply whether it's possible
to do a smooth one or not, just that nobody has a working idea yet.
E.g. it is possible that people try to leverage existing work (90% may
try to use type system extensions, for example) and find that it is too
unwieldy because the existing mechanisms aren't really suitable (e.g. it
may be that type systems in general are not very wellsuited to
expressing termination properties, leading us to the observation that
"research implementations seem rough").
> (Moreover, one of the advantages of laziness is precisely that one can
> write a function like take that works on both streams and lists).
That's exactly the relevant scenario.
Strictly speaking, all functions that iterate over all elements of the
list (say, takes its length) are buggy: They will not terminate if given
an infinite list.
The bad thing here is that in Haskell, generators and lists are exactly
the same, so there is no way to make a nonbuggy version of such a function.
(AFAIK, which doesn't say much because I haven't looked deeply enough
into Haskell in the last decade to be sure about this anymore. The
language did evolve after all.)
From jaro.reinders at gmail.com Thu Aug 1 07:58:15 2019
From: jaro.reinders at gmail.com (Jaro Reinders)
Date: Thu, 1 Aug 2019 09:58:15 +0200
Subject: [Haskellcafe] Performance best practices
InReplyTo:
References:
MessageID:
I think the best way to test the performance is to use a benchmarking
library such as criterion (http://www.serpentine.com/criterion/)
import Criterion.Main
import Data.List (inits,tails)
splits1, splits2, splits3 :: [a] > [([a],[a])]
splits1 xs = zip (inits xs) (tails xs)
splits2 [] = [([],[])]
splits2 xs@(x:xs') = ([],xs) : [(x:as,bs)  (as,bs) < splits2 xs']
splits3 = go id where
go prefix xs = (prefix [],xs) : case xs of
x:xs > go (prefix . (x :)) xs
[] > []
main = defaultMain
[ bench "splits1" $ nf splits1 input
, bench "splits2" $ nf splits2 input
, bench "splits3" $ nf splits3 input
]
where
input :: [Int]
input = [1..1000]
It gives the following results on my computer:
benchmarking splits1
time 4.693 ms (4.625 ms .. 4.752 ms)
0.999 R² (0.998 R² .. 0.999 R²)
mean 4.725 ms (4.694 ms .. 4.758 ms)
std dev 97.37 μs (77.95 μs .. 123.3 μs)
benchmarking splits2
time 12.10 ms (11.96 ms .. 12.25 ms)
0.999 R² (0.999 R² .. 1.000 R²)
mean 12.08 ms (12.03 ms .. 12.14 ms)
std dev 149.7 μs (110.0 μs .. 199.1 μs)
benchmarking splits3
time 4.110 ms (4.025 ms .. 4.187 ms)
0.997 R² (0.996 R² .. 0.999 R²)
mean 4.124 ms (4.081 ms .. 4.177 ms)
std dev 147.6 μs (115.6 μs .. 238.5 μs)
variance introduced by outliers: 17% (moderately inflated)
On 01082019 04:45, Todd Wilson wrote:
> Dear Cafe:
>
> I'm getting to the point in my Haskell learning curve where I'm
> getting more interested in the fine points of programming for
> performance and would be grateful for some ideas of the tools and
> options available for exploring this. To make this concrete, let me
> give a simple example. Here are two different ways of coding the same
> listsplitting function:
>
> import Data.List (inits,tails)
> splits1, splits2 :: [a] > [([a],[a])]
> splits1 xs = zip (inits xs) (tails xs)
> splits2 [] = [([],[])]
> splits2 xs@(x:xs') = ([],xs) : [(x:as,bs)  (as,bs) < splits2 xs']
>
> For example, splits1 [1,2,3] is
> [([],[1,2,3]),([1],[2,3]),([1,2],[3]),([1,2,3],[])].
>
> How do these functions compare in their actual time and space usage?
> It seems that, asymptotically, tails is O(n) while inits is O(n^2) in
> both time and space (when fully evaluated), and splits2 is also
> O(n^2), but how would I go about comparing them in actual usage to get
> a more precise comparison? What profiling or runtime statistics could
> I gather to make a decision about which one to use in a situation
> where performance mattered (assuming for the sake of discussion that
> such a situation existed for this simple example)? And, out of
> curiosity, is there an even more efficient way to code this function?
> Thanks,
>
> Todd Wilson
> _______________________________________________
> HaskellCafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
> Only members subscribed via the mailman list are allowed to post.
>
From jerzy.karczmarczuk at unicaen.fr Thu Aug 1 08:06:21 2019
From: jerzy.karczmarczuk at unicaen.fr (Jerzy Karczmarczuk)
Date: Thu, 1 Aug 2019 10:06:21 +0200
Subject: [Haskellcafe] ANN: To Kata Haskellen Evangelion
InReplyTo:
References:
<72ad2c39ee1f645684342f06c563e5ca@durchholz.org>
<3ae4443931a1d702a914699593b42621@durchholz.org>
MessageID: <68790283d740ae881f6f544c97203ea0@unicaen.fr>
Le 01/08/2019 à 07:50, Joachim Durchholz a écrit :
> Strictly speaking, all functions that iterate over all elements of the
> list (say, takes its length) *are buggy*: They will not terminate if
> given an infinite list.
I think that you have a curious definition of the term "buggy". This
definition is as buggy as the rest of the world (perhaps infinite...),
or more. You like to play with words. Now the nontermination is
"buggy". Previously the bottom (nontermination) was impure. Do you
really want to save the humanity with such statements?
Jerzy Karczmarczuk
 next part 
An HTML attachment was scrubbed...
URL:
From jaro.reinders at gmail.com Thu Aug 1 08:25:02 2019
From: jaro.reinders at gmail.com (Jaro Reinders)
Date: Thu, 1 Aug 2019 10:25:02 +0200
Subject: [Haskellcafe] Performance best practices
InReplyTo:
References:
MessageID:
If you fully evaluate the list produced by tails, then you're still
spending O(n^2) time, because that is just the size of the produced
list. But constructing the list and the memory taken by the list is
O(n), because most of the lists are shared
(https://wiki.haskell.org/Sharing).
On 01082019 04:45, Todd Wilson wrote:
> It seems that, asymptotically, tails is O(n) while inits is O(n^2) in
> both time and space (when fully evaluated)
From jo at durchholz.org Thu Aug 1 08:49:06 2019
From: jo at durchholz.org (Joachim Durchholz)
Date: Thu, 1 Aug 2019 10:49:06 +0200
Subject: [Haskellcafe] ANN: To Kata Haskellen Evangelion
InReplyTo: <68790283d740ae881f6f544c97203ea0@unicaen.fr>
References:
<72ad2c39ee1f645684342f06c563e5ca@durchholz.org>
<3ae4443931a1d702a914699593b42621@durchholz.org>
<68790283d740ae881f6f544c97203ea0@unicaen.fr>
MessageID:
Am 01.08.19 um 10:06 schrieb Jerzy Karczmarczuk:
>
> You like to play with words. Now the nontermination is
> "buggy". Previously the bottom (nontermination) was impure. Do you
> really want to save the humanity with such statements?
Nice play with words.
From jaro.reinders at gmail.com Thu Aug 1 09:04:19 2019
From: jaro.reinders at gmail.com (Jaro Reinders)
Date: Thu, 1 Aug 2019 11:04:19 +0200
Subject: [Haskellcafe] Performance best practices
InReplyTo:
References:
MessageID: <204c1c06487928acfd4babcdc3ea81b7@gmail.com>
Replying to myself, you can actually write an evaluation function that
forces all values in the result of tails and inits in linear time:
 force the result of tails in linear time
seqTails (x:xs) = x `deepseq` seqList xs
seqTails [] = ()
 force all the values in a list to whnf in linear time
 https://wiki.haskell.org/Weak_head_normal_form
seqList (x:xs) = x `seq` seqList xs
seqList [] = ()
 force the result of inits in linear time
seqInits xs = last xs `deepseq` seqList xs
Try it in ghci with :sprint
(https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html#ghcicmd:sprint):
> let x = tails [1..3::Int]
> :sprint x
x = _
> seqTails x
()
> :sprint x
x = [[1,2,3],[2,3],[3],[]]
> let y = inits [1..3::Int]
> :sprint y
y = _
> seqInits y
()
> :sprint y
y = [[],[1],[1,2],[1,2,3]]
Using criterion you can see that it is actually linear time:
main = defaultMain
[ bgroup "inits"
[ bench "1000" $ whnf (seqInits . inits) [1..1000 :: Int]
, bench "10000" $ whnf (seqInits . inits) [1..10000 :: Int]
, bench "100000" $ whnf (seqInits . inits) [1..100000 :: Int]
, bench "1000000" $ whnf (seqInits . inits) [1..1000000 :: Int]
]
, bgroup "tails"
[ bench "1000" $ whnf (seqTails . tails) [1..1000 :: Int]
, bench "10000" $ whnf (seqTails . tails) [1..10000 :: Int]
, bench "100000" $ whnf (seqTails . tails) [1..100000 :: Int]
, bench "1000000" $ whnf (seqTails . tails) [1..1000000 :: Int]
]
]
benchmarking inits/1000
time 204.2 μs (203.2 μs .. 205.4 μs)
1.000 R² (1.000 R² .. 1.000 R²)
mean 203.4 μs (202.8 μs .. 204.1 μs)
std dev 2.163 μs (1.755 μs .. 2.664 μs)
benchmarking inits/10000
time 3.127 ms (3.107 ms .. 3.148 ms)
1.000 R² (0.999 R² .. 1.000 R²)
mean 3.105 ms (3.088 ms .. 3.118 ms)
std dev 45.73 μs (32.97 μs .. 69.14 μs)
benchmarking inits/100000
time 41.05 ms (39.11 ms .. 42.87 ms)
0.993 R² (0.988 R² .. 0.998 R²)
mean 41.52 ms (40.62 ms .. 42.46 ms)
std dev 1.912 ms (1.330 ms .. 2.930 ms)
variance introduced by outliers: 12% (moderately inflated)
benchmarking inits/1000000
time 423.0 ms (318.2 ms .. 535.5 ms)
0.991 R² (0.969 R² .. 1.000 R²)
mean 459.1 ms (428.8 ms .. 505.2 ms)
std dev 44.05 ms (10.06 ms .. 58.49 ms)
variance introduced by outliers: 22% (moderately inflated)
benchmarking tails/1000
time 8.811 μs (8.768 μs .. 8.873 μs)
1.000 R² (0.999 R² .. 1.000 R²)
mean 8.874 μs (8.819 μs .. 8.963 μs)
std dev 225.7 ns (168.4 ns .. 325.2 ns)
variance introduced by outliers: 28% (moderately inflated)
benchmarking tails/10000
time 87.21 μs (86.85 μs .. 87.79 μs)
1.000 R² (0.999 R² .. 1.000 R²)
mean 87.42 μs (87.01 μs .. 87.88 μs)
std dev 1.481 μs (1.132 μs .. 1.953 μs)
variance introduced by outliers: 11% (moderately inflated)
benchmarking tails/100000
time 886.9 μs (882.9 μs .. 890.9 μs)
1.000 R² (1.000 R² .. 1.000 R²)
mean 881.5 μs (878.1 μs .. 885.7 μs)
std dev 12.40 μs (9.598 μs .. 18.97 μs)
benchmarking tails/1000000
time 9.796 ms (9.757 ms .. 9.840 ms)
1.000 R² (1.000 R² .. 1.000 R²)
mean 9.817 ms (9.791 ms .. 9.845 ms)
std dev 78.47 μs (60.63 μs .. 99.31 μs)
On 01082019 10:25, Jaro Reinders wrote:
> If you fully evaluate the list produced by tails, then you're still
> spending O(n^2) time, because that is just the size of the produced
> list. But constructing the list and the memory taken by the list is
> O(n), because most of the lists are shared
> (https://wiki.haskell.org/Sharing).
>
> On 01082019 04:45, Todd Wilson wrote:
>> It seems that, asymptotically, tails is O(n) while inits is O(n^2) in
>> both time and space (when fully evaluated)
From jaro.reinders at gmail.com Thu Aug 1 09:24:45 2019
From: jaro.reinders at gmail.com (Jaro Reinders)
Date: Thu, 1 Aug 2019 11:24:45 +0200
Subject: [Haskellcafe] Performance best practices
InReplyTo: <204c1c06487928acfd4babcdc3ea81b7@gmail.com>
References:
<204c1c06487928acfd4babcdc3ea81b7@gmail.com>
MessageID: <8e0e3b02be549d88a30eadd0bb8d9b13@gmail.com>
I just realized seqTails and seqInits are unnecessary, seqList is enough.
On 01082019 11:04, Jaro Reinders wrote:
> Replying to myself, you can actually write an evaluation function that
> forces all values in the result of tails and inits in linear time:
>
>  force the result of tails in linear time
> seqTails (x:xs) = x `deepseq` seqList xs
> seqTails [] = ()
>
>  force all the values in a list to whnf in linear time
>  https://wiki.haskell.org/Weak_head_normal_form
> seqList (x:xs) = x `seq` seqList xs
> seqList [] = ()
>
>  force the result of inits in linear time
> seqInits xs = last xs `deepseq` seqList xs
>
> Try it in ghci with :sprint
> (https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html#ghcicmd:sprint):
>
> > let x = tails [1..3::Int]
> > :sprint x
> x = _
> > seqTails x
> ()
> > :sprint x
> x = [[1,2,3],[2,3],[3],[]]
>
> > let y = inits [1..3::Int]
> > :sprint y
> y = _
> > seqInits y
> ()
> > :sprint y
> y = [[],[1],[1,2],[1,2,3]]
>
> Using criterion you can see that it is actually linear time:
>
> main = defaultMain
> [ bgroup "inits"
> [ bench "1000" $ whnf (seqInits . inits) [1..1000 :: Int]
> , bench "10000" $ whnf (seqInits . inits) [1..10000 :: Int]
> , bench "100000" $ whnf (seqInits . inits) [1..100000 :: Int]
> , bench "1000000" $ whnf (seqInits . inits) [1..1000000 :: Int]
> ]
> , bgroup "tails"
> [ bench "1000" $ whnf (seqTails . tails) [1..1000 :: Int]
> , bench "10000" $ whnf (seqTails . tails) [1..10000 :: Int]
> , bench "100000" $ whnf (seqTails . tails) [1..100000 :: Int]
> , bench "1000000" $ whnf (seqTails . tails) [1..1000000 :: Int]
> ]
> ]
>
>
> benchmarking inits/1000
> time 204.2 μs (203.2 μs .. 205.4 μs)
> 1.000 R² (1.000 R² .. 1.000 R²)
> mean 203.4 μs (202.8 μs .. 204.1 μs)
> std dev 2.163 μs (1.755 μs .. 2.664 μs)
>
> benchmarking inits/10000
> time 3.127 ms (3.107 ms .. 3.148 ms)
> 1.000 R² (0.999 R² .. 1.000 R²)
> mean 3.105 ms (3.088 ms .. 3.118 ms)
> std dev 45.73 μs (32.97 μs .. 69.14 μs)
>
> benchmarking inits/100000
> time 41.05 ms (39.11 ms .. 42.87 ms)
> 0.993 R² (0.988 R² .. 0.998 R²)
> mean 41.52 ms (40.62 ms .. 42.46 ms)
> std dev 1.912 ms (1.330 ms .. 2.930 ms)
> variance introduced by outliers: 12% (moderately inflated)
>
> benchmarking inits/1000000
> time 423.0 ms (318.2 ms .. 535.5 ms)
> 0.991 R² (0.969 R² .. 1.000 R²)
> mean 459.1 ms (428.8 ms .. 505.2 ms)
> std dev 44.05 ms (10.06 ms .. 58.49 ms)
> variance introduced by outliers: 22% (moderately inflated)
>
>
>
> benchmarking tails/1000
> time 8.811 μs (8.768 μs .. 8.873 μs)
> 1.000 R² (0.999 R² .. 1.000 R²)
> mean 8.874 μs (8.819 μs .. 8.963 μs)
> std dev 225.7 ns (168.4 ns .. 325.2 ns)
> variance introduced by outliers: 28% (moderately inflated)
>
> benchmarking tails/10000
> time 87.21 μs (86.85 μs .. 87.79 μs)
> 1.000 R² (0.999 R² .. 1.000 R²)
> mean 87.42 μs (87.01 μs .. 87.88 μs)
> std dev 1.481 μs (1.132 μs .. 1.953 μs)
> variance introduced by outliers: 11% (moderately inflated)
>
> benchmarking tails/100000
> time 886.9 μs (882.9 μs .. 890.9 μs)
> 1.000 R² (1.000 R² .. 1.000 R²)
> mean 881.5 μs (878.1 μs .. 885.7 μs)
> std dev 12.40 μs (9.598 μs .. 18.97 μs)
>
> benchmarking tails/1000000
> time 9.796 ms (9.757 ms .. 9.840 ms)
> 1.000 R² (1.000 R² .. 1.000 R²)
> mean 9.817 ms (9.791 ms .. 9.845 ms)
> std dev 78.47 μs (60.63 μs .. 99.31 μs)
>
>
> On 01082019 10:25, Jaro Reinders wrote:
>> If you fully evaluate the list produced by tails, then you're still
>> spending O(n^2) time, because that is just the size of the produced
>> list. But constructing the list and the memory taken by the list is
>> O(n), because most of the lists are shared
>> (https://wiki.haskell.org/Sharing).
>>
>> On 01082019 04:45, Todd Wilson wrote:
>>> It seems that, asymptotically, tails is O(n) while inits is O(n^2) in
>>> both time and space (when fully evaluated)
From will.yager at gmail.com Thu Aug 1 10:48:07 2019
From: will.yager at gmail.com (William Yager)
Date: Thu, 1 Aug 2019 18:48:07 +0800
Subject: [Haskellcafe] Performance best practices
InReplyTo: <8e0e3b02be549d88a30eadd0bb8d9b13@gmail.com>
References:
<204c1c06487928acfd4babcdc3ea81b7@gmail.com>
<8e0e3b02be549d88a30eadd0bb8d9b13@gmail.com>
MessageID:
In high performance Haskell, you will often find yourself using sequential
structures besides lists. For example, an unboxed vector implementation is
over 100x faster than any of the proposed list implementations.
Code: https://gist.github.com/wyager/45946f9f1531351468e4366b7ba168fa
Benchmark result:
https://gist.github.com/wyager/96e7876a4b170d83dca971dd152e475e
GHC is very powerful, and can often do a surprisingly good job of
optimizing away list allocations and such. However, in sharingheavy
applications like this (and if random indexing is helpful), Vectors can be
much more efficient.
On Thu, Aug 1, 2019 at 5:25 PM Jaro Reinders
wrote:
> I just realized seqTails and seqInits are unnecessary, seqList is enough.
>
> On 01082019 11:04, Jaro Reinders wrote:
> > Replying to myself, you can actually write an evaluation function that
> > forces all values in the result of tails and inits in linear time:
> >
> >  force the result of tails in linear time
> > seqTails (x:xs) = x `deepseq` seqList xs
> > seqTails [] = ()
> >
> >  force all the values in a list to whnf in linear time
> >  https://wiki.haskell.org/Weak_head_normal_form
> > seqList (x:xs) = x `seq` seqList xs
> > seqList [] = ()
> >
> >  force the result of inits in linear time
> > seqInits xs = last xs `deepseq` seqList xs
> >
> > Try it in ghci with :sprint
> > (
> https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html#ghcicmd:sprint
> ):
> >
> > > let x = tails [1..3::Int]
> > > :sprint x
> > x = _
> > > seqTails x
> > ()
> > > :sprint x
> > x = [[1,2,3],[2,3],[3],[]]
> >
> > > let y = inits [1..3::Int]
> > > :sprint y
> > y = _
> > > seqInits y
> > ()
> > > :sprint y
> > y = [[],[1],[1,2],[1,2,3]]
> >
> > Using criterion you can see that it is actually linear time:
> >
> > main = defaultMain
> > [ bgroup "inits"
> > [ bench "1000" $ whnf (seqInits . inits) [1..1000 :: Int]
> > , bench "10000" $ whnf (seqInits . inits) [1..10000 :: Int]
> > , bench "100000" $ whnf (seqInits . inits) [1..100000 :: Int]
> > , bench "1000000" $ whnf (seqInits . inits) [1..1000000 :: Int]
> > ]
> > , bgroup "tails"
> > [ bench "1000" $ whnf (seqTails . tails) [1..1000 :: Int]
> > , bench "10000" $ whnf (seqTails . tails) [1..10000 :: Int]
> > , bench "100000" $ whnf (seqTails . tails) [1..100000 :: Int]
> > , bench "1000000" $ whnf (seqTails . tails) [1..1000000 :: Int]
> > ]
> > ]
> >
> >
> > benchmarking inits/1000
> > time 204.2 μs (203.2 μs .. 205.4 μs)
> > 1.000 R² (1.000 R² .. 1.000 R²)
> > mean 203.4 μs (202.8 μs .. 204.1 μs)
> > std dev 2.163 μs (1.755 μs .. 2.664 μs)
> >
> > benchmarking inits/10000
> > time 3.127 ms (3.107 ms .. 3.148 ms)
> > 1.000 R² (0.999 R² .. 1.000 R²)
> > mean 3.105 ms (3.088 ms .. 3.118 ms)
> > std dev 45.73 μs (32.97 μs .. 69.14 μs)
> >
> > benchmarking inits/100000
> > time 41.05 ms (39.11 ms .. 42.87 ms)
> > 0.993 R² (0.988 R² .. 0.998 R²)
> > mean 41.52 ms (40.62 ms .. 42.46 ms)
> > std dev 1.912 ms (1.330 ms .. 2.930 ms)
> > variance introduced by outliers: 12% (moderately inflated)
> >
> > benchmarking inits/1000000
> > time 423.0 ms (318.2 ms .. 535.5 ms)
> > 0.991 R² (0.969 R² .. 1.000 R²)
> > mean 459.1 ms (428.8 ms .. 505.2 ms)
> > std dev 44.05 ms (10.06 ms .. 58.49 ms)
> > variance introduced by outliers: 22% (moderately inflated)
> >
> >
> >
> > benchmarking tails/1000
> > time 8.811 μs (8.768 μs .. 8.873 μs)
> > 1.000 R² (0.999 R² .. 1.000 R²)
> > mean 8.874 μs (8.819 μs .. 8.963 μs)
> > std dev 225.7 ns (168.4 ns .. 325.2 ns)
> > variance introduced by outliers: 28% (moderately inflated)
> >
> > benchmarking tails/10000
> > time 87.21 μs (86.85 μs .. 87.79 μs)
> > 1.000 R² (0.999 R² .. 1.000 R²)
> > mean 87.42 μs (87.01 μs .. 87.88 μs)
> > std dev 1.481 μs (1.132 μs .. 1.953 μs)
> > variance introduced by outliers: 11% (moderately inflated)
> >
> > benchmarking tails/100000
> > time 886.9 μs (882.9 μs .. 890.9 μs)
> > 1.000 R² (1.000 R² .. 1.000 R²)
> > mean 881.5 μs (878.1 μs .. 885.7 μs)
> > std dev 12.40 μs (9.598 μs .. 18.97 μs)
> >
> > benchmarking tails/1000000
> > time 9.796 ms (9.757 ms .. 9.840 ms)
> > 1.000 R² (1.000 R² .. 1.000 R²)
> > mean 9.817 ms (9.791 ms .. 9.845 ms)
> > std dev 78.47 μs (60.63 μs .. 99.31 μs)
> >
> >
> > On 01082019 10:25, Jaro Reinders wrote:
> >> If you fully evaluate the list produced by tails, then you're still
> >> spending O(n^2) time, because that is just the size of the produced
> >> list. But constructing the list and the memory taken by the list is
> >> O(n), because most of the lists are shared
> >> (https://wiki.haskell.org/Sharing).
> >>
> >> On 01082019 04:45, Todd Wilson wrote:
> >>> It seems that, asymptotically, tails is O(n) while inits is O(n^2) in
> >>> both time and space (when fully evaluated)
> _______________________________________________
> HaskellCafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
> Only members subscribed via the mailman list are allowed to post.
 next part 
An HTML attachment was scrubbed...
URL:
From will.yager at gmail.com Thu Aug 1 10:54:40 2019
From: will.yager at gmail.com (William Yager)
Date: Thu, 1 Aug 2019 18:54:40 +0800
Subject: [Haskellcafe] Request for Comments
InReplyTo:
References:
MessageID:
This looks quite interesting, but I'm not sure how to read the examples.
Could you perhaps explain some more how to traverse the matrix, and also
provide a normal assembly program along with the matrix representation?
On Thu, Aug 1, 2019 at 2:26 AM ibrahim Sagiroglu
wrote:
> Hello all,
>
> I have an attempt to present llvm assembly in [1]. Would you consider
> taking some time to comment on it?
>
> [1] https://github.com/ibrahimsag/rw
> _______________________________________________
> HaskellCafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
> Only members subscribed via the mailman list are allowed to post.
 next part 
An HTML attachment was scrubbed...
URL:
From jaro.reinders at gmail.com Thu Aug 1 10:54:57 2019
From: jaro.reinders at gmail.com (Jaro Reinders)
Date: Thu, 1 Aug 2019 12:54:57 +0200
Subject: [Haskellcafe] Performance best practices
InReplyTo:
References:
<204c1c06487928acfd4babcdc3ea81b7@gmail.com>
<8e0e3b02be549d88a30eadd0bb8d9b13@gmail.com>
MessageID: <8eb5ad55c0496acf8814978c6b22ef46@gmail.com>
To make the comparison more fair you should use the seqList function
instead of nf for evaluation the list functions. Then the list version
is actually faster (*sl is with my seqList function):
benchmarking splits1
time 4.799 ms (4.751 ms .. 4.857 ms)
0.999 R² (0.998 R² .. 0.999 R²)
mean 4.854 ms (4.821 ms .. 4.893 ms)
std dev 111.0 μs (90.31 μs .. 136.2 μs)
benchmarking splits2
time 12.18 ms (11.93 ms .. 12.53 ms)
0.995 R² (0.990 R² .. 0.999 R²)
mean 12.82 ms (12.61 ms .. 13.04 ms)
std dev 568.8 μs (514.4 μs .. 636.1 μs)
variance introduced by outliers: 18% (moderately inflated)
benchmarking splits3
time 4.118 ms (4.067 ms .. 4.164 ms)
0.999 R² (0.998 R² .. 0.999 R²)
mean 4.186 ms (4.154 ms .. 4.229 ms)
std dev 114.2 μs (89.12 μs .. 144.2 μs)
variance introduced by outliers: 11% (moderately inflated)
benchmarking splits1sl
time 24.91 μs (24.78 μs .. 25.04 μs)
1.000 R² (1.000 R² .. 1.000 R²)
mean 24.78 μs (24.67 μs .. 24.89 μs)
std dev 378.3 ns (317.1 ns .. 466.5 ns)
variance introduced by outliers: 11% (moderately inflated)
benchmarking splits2sl
time 8.903 ms (8.835 ms .. 8.962 ms)
1.000 R² (0.999 R² .. 1.000 R²)
mean 8.877 ms (8.834 ms .. 8.924 ms)
std dev 124.0 μs (104.2 μs .. 147.1 μs)
benchmarking splits3sl
time 11.54 μs (11.49 μs .. 11.58 μs)
1.000 R² (1.000 R² .. 1.000 R²)
mean 11.59 μs (11.54 μs .. 11.64 μs)
std dev 156.7 ns (127.7 ns .. 207.3 ns)
benchmarking splits4 (boxed)
time 1.903 ms (1.894 ms .. 1.910 ms)
1.000 R² (1.000 R² .. 1.000 R²)
mean 1.908 ms (1.901 ms .. 1.915 ms)
std dev 25.61 μs (20.81 μs .. 31.73 μs)
benchmarking splits4 (unboxed)
time 33.63 μs (33.51 μs .. 33.74 μs)
1.000 R² (1.000 R² .. 1.000 R²)
mean 33.60 μs (33.46 μs .. 33.76 μs)
std dev 493.7 ns (386.8 ns .. 622.1 ns)
variance introduced by outliers: 10% (moderately inflated)
On 01082019 12:48, William Yager wrote:
> In high performance Haskell, you will often find yourself using sequential
> structures besides lists. For example, an unboxed vector implementation is
> over 100x faster than any of the proposed list implementations.
>
> Code: https://gist.github.com/wyager/45946f9f1531351468e4366b7ba168fa
>
> Benchmark result:
> https://gist.github.com/wyager/96e7876a4b170d83dca971dd152e475e
>
> GHC is very powerful, and can often do a surprisingly good job of
> optimizing away list allocations and such. However, in sharingheavy
> applications like this (and if random indexing is helpful), Vectors can be
> much more efficient.
>
> On Thu, Aug 1, 2019 at 5:25 PM Jaro Reinders
> wrote:
>
>> I just realized seqTails and seqInits are unnecessary, seqList is enough.
>>
>> On 01082019 11:04, Jaro Reinders wrote:
>>> Replying to myself, you can actually write an evaluation function that
>>> forces all values in the result of tails and inits in linear time:
>>>
>>>  force the result of tails in linear time
>>> seqTails (x:xs) = x `deepseq` seqList xs
>>> seqTails [] = ()
>>>
>>>  force all the values in a list to whnf in linear time
>>>  https://wiki.haskell.org/Weak_head_normal_form
>>> seqList (x:xs) = x `seq` seqList xs
>>> seqList [] = ()
>>>
>>>  force the result of inits in linear time
>>> seqInits xs = last xs `deepseq` seqList xs
>>>
>>> Try it in ghci with :sprint
>>> (
>> https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html#ghcicmd:sprint
>> ):
>>>
>>> > let x = tails [1..3::Int]
>>> > :sprint x
>>> x = _
>>> > seqTails x
>>> ()
>>> > :sprint x
>>> x = [[1,2,3],[2,3],[3],[]]
>>>
>>> > let y = inits [1..3::Int]
>>> > :sprint y
>>> y = _
>>> > seqInits y
>>> ()
>>> > :sprint y
>>> y = [[],[1],[1,2],[1,2,3]]
>>>
>>> Using criterion you can see that it is actually linear time:
>>>
>>> main = defaultMain
>>> [ bgroup "inits"
>>> [ bench "1000" $ whnf (seqInits . inits) [1..1000 :: Int]
>>> , bench "10000" $ whnf (seqInits . inits) [1..10000 :: Int]
>>> , bench "100000" $ whnf (seqInits . inits) [1..100000 :: Int]
>>> , bench "1000000" $ whnf (seqInits . inits) [1..1000000 :: Int]
>>> ]
>>> , bgroup "tails"
>>> [ bench "1000" $ whnf (seqTails . tails) [1..1000 :: Int]
>>> , bench "10000" $ whnf (seqTails . tails) [1..10000 :: Int]
>>> , bench "100000" $ whnf (seqTails . tails) [1..100000 :: Int]
>>> , bench "1000000" $ whnf (seqTails . tails) [1..1000000 :: Int]
>>> ]
>>> ]
>>>
>>>
>>> benchmarking inits/1000
>>> time 204.2 μs (203.2 μs .. 205.4 μs)
>>> 1.000 R² (1.000 R² .. 1.000 R²)
>>> mean 203.4 μs (202.8 μs .. 204.1 μs)
>>> std dev 2.163 μs (1.755 μs .. 2.664 μs)
>>>
>>> benchmarking inits/10000
>>> time 3.127 ms (3.107 ms .. 3.148 ms)
>>> 1.000 R² (0.999 R² .. 1.000 R²)
>>> mean 3.105 ms (3.088 ms .. 3.118 ms)
>>> std dev 45.73 μs (32.97 μs .. 69.14 μs)
>>>
>>> benchmarking inits/100000
>>> time 41.05 ms (39.11 ms .. 42.87 ms)
>>> 0.993 R² (0.988 R² .. 0.998 R²)
>>> mean 41.52 ms (40.62 ms .. 42.46 ms)
>>> std dev 1.912 ms (1.330 ms .. 2.930 ms)
>>> variance introduced by outliers: 12% (moderately inflated)
>>>
>>> benchmarking inits/1000000
>>> time 423.0 ms (318.2 ms .. 535.5 ms)
>>> 0.991 R² (0.969 R² .. 1.000 R²)
>>> mean 459.1 ms (428.8 ms .. 505.2 ms)
>>> std dev 44.05 ms (10.06 ms .. 58.49 ms)
>>> variance introduced by outliers: 22% (moderately inflated)
>>>
>>>
>>>
>>> benchmarking tails/1000
>>> time 8.811 μs (8.768 μs .. 8.873 μs)
>>> 1.000 R² (0.999 R² .. 1.000 R²)
>>> mean 8.874 μs (8.819 μs .. 8.963 μs)
>>> std dev 225.7 ns (168.4 ns .. 325.2 ns)
>>> variance introduced by outliers: 28% (moderately inflated)
>>>
>>> benchmarking tails/10000
>>> time 87.21 μs (86.85 μs .. 87.79 μs)
>>> 1.000 R² (0.999 R² .. 1.000 R²)
>>> mean 87.42 μs (87.01 μs .. 87.88 μs)
>>> std dev 1.481 μs (1.132 μs .. 1.953 μs)
>>> variance introduced by outliers: 11% (moderately inflated)
>>>
>>> benchmarking tails/100000
>>> time 886.9 μs (882.9 μs .. 890.9 μs)
>>> 1.000 R² (1.000 R² .. 1.000 R²)
>>> mean 881.5 μs (878.1 μs .. 885.7 μs)
>>> std dev 12.40 μs (9.598 μs .. 18.97 μs)
>>>
>>> benchmarking tails/1000000
>>> time 9.796 ms (9.757 ms .. 9.840 ms)
>>> 1.000 R² (1.000 R² .. 1.000 R²)
>>> mean 9.817 ms (9.791 ms .. 9.845 ms)
>>> std dev 78.47 μs (60.63 μs .. 99.31 μs)
>>>
>>>
>>> On 01082019 10:25, Jaro Reinders wrote:
>>>> If you fully evaluate the list produced by tails, then you're still
>>>> spending O(n^2) time, because that is just the size of the produced
>>>> list. But constructing the list and the memory taken by the list is
>>>> O(n), because most of the lists are shared
>>>> (https://wiki.haskell.org/Sharing).
>>>>
>>>> On 01082019 04:45, Todd Wilson wrote:
>>>>> It seems that, asymptotically, tails is O(n) while inits is O(n^2) in
>>>>> both time and space (when fully evaluated)
>> _______________________________________________
>> HaskellCafe mailing list
>> To (un)subscribe, modify options or view archives go to:
>> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
>> Only members subscribed via the mailman list are allowed to post.
>
From sag.ibrahim at gmail.com Thu Aug 1 11:05:09 2019
From: sag.ibrahim at gmail.com (ibrahim Sagiroglu)
Date: Thu, 1 Aug 2019 14:05:09 +0300
Subject: [Haskellcafe] Request for Comments
InReplyTo:
References:
MessageID:
assembly programs are in the ex folder. i should have mentioned that, thank
you.
Sequence of instructions are along the diagonal. register and label
bindings are represented by other cells. maybe read it as a particular
restriction on graph edges.
You start from bottom, climb up to the top, the climbing was so interesting
intuition to miss and also that the arguments are on the right.
On 1 Aug 2019 Thu at 13:54 William Yager wrote:
> This looks quite interesting, but I'm not sure how to read the examples.
> Could you perhaps explain some more how to traverse the matrix, and also
> provide a normal assembly program along with the matrix representation?
>
> On Thu, Aug 1, 2019 at 2:26 AM ibrahim Sagiroglu
> wrote:
>
>> Hello all,
>>
>> I have an attempt to present llvm assembly in [1]. Would you consider
>> taking some time to comment on it?
>>
>> [1] https://github.com/ibrahimsag/rw
>>
> _______________________________________________
>> HaskellCafe mailing list
>> To (un)subscribe, modify options or view archives go to:
>> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
>> Only members subscribed via the mailman list are allowed to post.
>
>
 next part 
An HTML attachment was scrubbed...
URL:
From sag.ibrahim at gmail.com Thu Aug 1 14:56:12 2019
From: sag.ibrahim at gmail.com (ibrahim Sagiroglu)
Date: Thu, 1 Aug 2019 17:56:12 +0300
Subject: [Haskellcafe] Request for Comments
InReplyTo:
References:
MessageID:
Placed the code next to generated images in readme. Should not be further
difficulties.
I expect this to be useful for all sorts of ui needs. it is as intuitive as
excel but much more. help me push it in the open.
The idea is that a sparse adjacency matrix is just as friendly as any other
graph layout. Especially when the diagonal cells strategically utilized.
And exponentially more powerful since it can provide arbitrary details.
On 1 Aug 2019 Thu at 14:05 ibrahim Sagiroglu wrote:
> assembly programs are in the ex folder. i should have mentioned that,
> thank you.
>
> Sequence of instructions are along the diagonal. register and label
> bindings are represented by other cells. maybe read it as a particular
> restriction on graph edges.
>
> You start from bottom, climb up to the top, the climbing was so
> interesting intuition to miss and also that the arguments are on the right.
>
> On 1 Aug 2019 Thu at 13:54 William Yager wrote:
>
>> This looks quite interesting, but I'm not sure how to read the examples.
>> Could you perhaps explain some more how to traverse the matrix, and also
>> provide a normal assembly program along with the matrix representation?
>>
>> On Thu, Aug 1, 2019 at 2:26 AM ibrahim Sagiroglu
>> wrote:
>>
>>> Hello all,
>>>
>>> I have an attempt to present llvm assembly in [1]. Would you consider
>>> taking some time to comment on it?
>>>
>>> [1] https://github.com/ibrahimsag/rw
>>>
>> _______________________________________________
>>> HaskellCafe mailing list
>>> To (un)subscribe, modify options or view archives go to:
>>> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
>>> Only members subscribed via the mailman list are allowed to post.
>>
>>
 next part 
An HTML attachment was scrubbed...
URL:
From dsf at seereason.com Fri Aug 2 21:42:19 2019
From: dsf at seereason.com (David Fox)
Date: Fri, 2 Aug 2019 14:42:19 0700
Subject: [Haskellcafe] ANN: To Kata Haskellen Evangelion
InReplyTo:
References:
MessageID:
I would say that the constraint means you can assume that the Eq instance
exists when writing your Ord instance. If you try to write an Ord instance
for a type with no Eq instance the compiler will complain, even though it
might be possible to write the instance without using the Eq instance. I
would mention that putting constraints on the class is often overkill, it
may be better to put them on the individual instances as needed. But that
may be too much information for a beginner.
On Sun, Jul 28, 2019 at 8:51 AM David Fox wrote:
> On page 39 you say
>
> A type can have Ord instance only when it has Eq instance, since if
>> you want to compare items, you need a way to test if they are equal.
>
>
> So from my reading of this you are saying that an Eq instance for a type
> needs to be supplied before we are allowed to implement compare. However
> it is easy to write a compare function that makes no use of the underlying
> (==) function. Indeed, once you have done this you can turn around and
> write a == b = compare a b == EQ. So I was wondering if you could clarify
> the role of constraints in the class declaration.
>
> On Sun, Jul 28, 2019 at 2:38 AM Cosmia Fu wrote:
>
>> Hi everyone,
>>
>> Though some of you might already knows, I'm pleased to announce a new
>> Haskell book,
>> *To Kata Haskellen Evangelion*.
>> Link: https://cosmius.bitbucket.io/tkhe/
>> I believe that it does not have to be hard to learn Haskell.
>>
>> I begun to write the book in 2017 December, and... to be honest,
>> I don't know what to write now, though I still think it incomplete.
>> It will probably not be updated for quite a while.
>> So I decide to announce it earlier.
>>
>> I am not a native English speaker, so it might be not fluent or even with
>> a lot of grammar mistakes.
>> It would be very nice of you if you can tell me the mistakes in it,
>> factual, technical or grammar.
>> And also feel free to tell me if you want to read some topic in it.
>>
>> Thank you
>>
>> 
>>
>> Cosmia Fu
>> _______________________________________________
>> HaskellCafe mailing list
>> To (un)subscribe, modify options or view archives go to:
>> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
>> Only members subscribed via the mailman list are allowed to post.
>
>
 next part 
An HTML attachment was scrubbed...
URL:
From ben.franksen at online.de Fri Aug 2 23:38:38 2019
From: ben.franksen at online.de (Benjamin Franksen)
Date: Sat, 3 Aug 2019 01:38:38 +0200
Subject: [Haskellcafe] instance Monoid a => Monad ((,) a)
MessageID:
I wanted to define a simple Monad instance for (Bool,) as
instance Monad ((,) Bool) where
return x = (False, x)
(True, x) >>= k = (True, snd (k x))
(False, x) >>= k = k x
 or: (b, x) >>= k = let (c, y) = k x in (bc, y)
The idea was to keep track of whether functions change their input value
or not.
To my astonishment I found that this definition overlaps with an
existing one. GHC tells me
x.hs:2:10: error:
• No instance for (Monoid Bool)
arising from the superclasses of an instance declaration
• In the instance declaration for ‘Monad ((,) Bool)’

2  instance Monad ((,) Bool) where
 ^^^^^^^^^^^^^^^^
x.hs:2:10: error:
• Overlapping instances for Monad ((,) Bool)
arising from a use of ‘GHC.Base.$dm>>’
Matching instances:
instance Monoid a => Monad ((,) a)  Defined in ‘GHC.Base’
instance Monad ((,) Bool)  Defined at x.hs:2:10
• In the expression: GHC.Base.$dm>> @((,) Bool)
In an equation for ‘>>’: (>>) = GHC.Base.$dm>> @((,) Bool)
In the instance declaration for ‘Monad ((,) Bool)’

2  instance Monad ((,) Bool) where
 ^^^^^^^^^^^^^^^^
[one more similar overlap error elided]
But I could not find the
instance Monoid a => Monad ((,) a)
documented anywhere in the base package. Should I look harder? Or is
this instance accidentally leaking from GHC.Base?
Eventually, through some experimenting I found that if I replace Bool
with Any, then the existing instance seems to do what I want.
Cheers
Ben
From neil_mayhew at users.sourceforge.net Fri Aug 2 23:48:52 2019
From: neil_mayhew at users.sourceforge.net (Neil Mayhew)
Date: Fri, 2 Aug 2019 17:48:52 0600
Subject: [Haskellcafe] instance Monoid a => Monad ((,) a)
InReplyTo:
References:
MessageID:
On 20190802 5:38 p.m., Benjamin Franksen wrote:
But I could not find the
instance Monoid a => Monad ((,) a)
documented anywhere in the base package.
If you look at the list of instances under the definition of Monad,
you’ll see Monoid a => Monad ((,) a)  /Since: 4.9.0.0/ in the list.
Clicking on the # Source link takes you to the source of GHC.Base:
instance Monoid a => Monad ((,) a) where (u, a) >>= k = case k a of (v,
b) > (u <> v, b) 
 next part 
An HTML attachment was scrubbed...
URL:
From ben.franksen at online.de Sat Aug 3 08:57:14 2019
From: ben.franksen at online.de (Ben Franksen)
Date: Sat, 3 Aug 2019 10:57:14 +0200
Subject: [Haskellcafe] instance Monoid a => Monad ((,) a)
InReplyTo:
References:
MessageID:
Am 03.08.19 um 01:48 schrieb Neil Mayhew:
> On 20190802 5:38 p.m., Benjamin Franksen wrote:
>
> But I could not find the
>
> instance Monoid a => Monad ((,) a)
>
> documented anywhere in the base package.
>
> If you look at the list of instances under the definition of Monad,
> you’ll see Monoid a => Monad ((,) a)  /Since: 4.9.0.0/ in the list.
> Clicking on the # Source link takes you to the source of GHC.Base:
>
> instance Monoid a => Monad ((,) a) where (u, a) >>= k = case k a of (v,
> b) > (u <> v, b) 
Thanks! No idea how/why I missed that. I have stared at that list for
quite some time before sending my question, just couldn' see it...
And yes, this is exactly the instance I had in mind (with Any instead of
Bool).
Cheers
Ben
From bertram.felgenhauer at googlemail.com Sun Aug 4 06:43:14 2019
From: bertram.felgenhauer at googlemail.com (Bertram Felgenhauer)
Date: Sun, 4 Aug 2019 08:43:14 +0200
Subject: [Haskellcafe] Performance best practices
InReplyTo:
References:
MessageID: <20190804064314.GA3615@24f89f8ce6a14e7585eebb8a3743bb9f>
Todd Wilson wrote:
> For example, splits1 [1,2,3] is
> [([],[1,2,3]),([1],[2,3]),([1,2],[3]),([1,2,3],[])].
Note that `inits` (and hence `splits`) on lists is inherently quadratic,
because the resulting lists [1], [1,2], [1,2,3], and so on, cannot share
any parts of their spines. The only way around this is to change the
result, either the type (as suggested elsewhere in this list), or the
result itself. A cute option is to produce reversed lists, which can be
achieved by
rinits = scanl (flip (:)) []
(so `rinits [1,2,3] = [[],[1],[2,1],[3,2,1]]`). This works on plain
lists, and uses linear time and memory.
(One can view this as changing the result type to a list of snoc lists.
This fact can be expressed using a newtype wrapper or a custom list type
if desired.)
Cheers,
Bertram
From zhujinxuan at gmail.com Mon Aug 5 20:33:33 2019
From: zhujinxuan at gmail.com (Jinxuan Zhu)
Date: Mon, 5 Aug 2019 16:33:33 0400
Subject: [Haskellcafe] instance Monoid a => Monad ((,) a)
InReplyTo:
References:
MessageID:
Hi, I think the error message says there is no Monoid for Bool. It is
because Bool can be monoid by either  or && operations, which would lead
to ambiguity if Bool is monoid by default.
You can:
1. use Maybe Unit instead
2. (overkill) Define AndMonoid Bool newtype and use DeriveVia and coerce
On Fri, Aug 2, 2019 at 7:39 PM Benjamin Franksen
wrote:
> I wanted to define a simple Monad instance for (Bool,) as
>
> instance Monad ((,) Bool) where
> return x = (False, x)
> (True, x) >>= k = (True, snd (k x))
> (False, x) >>= k = k x
>  or: (b, x) >>= k = let (c, y) = k x in (bc, y)
>
> The idea was to keep track of whether functions change their input value
> or not.
>
> To my astonishment I found that this definition overlaps with an
> existing one. GHC tells me
>
> x.hs:2:10: error:
> • No instance for (Monoid Bool)
> arising from the superclasses of an instance declaration
> • In the instance declaration for ‘Monad ((,) Bool)’
> 
> 2  instance Monad ((,) Bool) where
>  ^^^^^^^^^^^^^^^^
>
> x.hs:2:10: error:
> • Overlapping instances for Monad ((,) Bool)
> arising from a use of ‘GHC.Base.$dm>>’
> Matching instances:
> instance Monoid a => Monad ((,) a)  Defined in ‘GHC.Base’
> instance Monad ((,) Bool)  Defined at x.hs:2:10
> • In the expression: GHC.Base.$dm>> @((,) Bool)
> In an equation for ‘>>’: (>>) = GHC.Base.$dm>> @((,) Bool)
> In the instance declaration for ‘Monad ((,) Bool)’
> 
> 2  instance Monad ((,) Bool) where
>  ^^^^^^^^^^^^^^^^
>
> [one more similar overlap error elided]
>
> But I could not find the
>
> instance Monoid a => Monad ((,) a)
>
> documented anywhere in the base package. Should I look harder? Or is
> this instance accidentally leaking from GHC.Base?
>
> Eventually, through some experimenting I found that if I replace Bool
> with Any, then the existing instance seems to do what I want.
>
> Cheers
> Ben
>
> _______________________________________________
> HaskellCafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
> Only members subscribed via the mailman list are allowed to post.
 next part 
An HTML attachment was scrubbed...
URL:
From david.feuer at gmail.com Mon Aug 5 20:49:41 2019
From: david.feuer at gmail.com (David Feuer)
Date: Mon, 5 Aug 2019 16:49:41 0400
Subject: [Haskellcafe] instance Monoid a => Monad ((,) a)
InReplyTo:
References:
MessageID:
Bool is also a monoid under xor.
On Mon, Aug 5, 2019, 4:34 PM Jinxuan Zhu wrote:
> Hi, I think the error message says there is no Monoid for Bool. It is
> because Bool can be monoid by either  or && operations, which would lead
> to ambiguity if Bool is monoid by default.
>
> You can:
> 1. use Maybe Unit instead
> 2. (overkill) Define AndMonoid Bool newtype and use DeriveVia and coerce
>
>
>
> On Fri, Aug 2, 2019 at 7:39 PM Benjamin Franksen
> wrote:
>
>> I wanted to define a simple Monad instance for (Bool,) as
>>
>> instance Monad ((,) Bool) where
>> return x = (False, x)
>> (True, x) >>= k = (True, snd (k x))
>> (False, x) >>= k = k x
>>  or: (b, x) >>= k = let (c, y) = k x in (bc, y)
>>
>> The idea was to keep track of whether functions change their input value
>> or not.
>>
>> To my astonishment I found that this definition overlaps with an
>> existing one. GHC tells me
>>
>> x.hs:2:10: error:
>> • No instance for (Monoid Bool)
>> arising from the superclasses of an instance declaration
>> • In the instance declaration for ‘Monad ((,) Bool)’
>> 
>> 2  instance Monad ((,) Bool) where
>>  ^^^^^^^^^^^^^^^^
>>
>> x.hs:2:10: error:
>> • Overlapping instances for Monad ((,) Bool)
>> arising from a use of ‘GHC.Base.$dm>>’
>> Matching instances:
>> instance Monoid a => Monad ((,) a)  Defined in ‘GHC.Base’
>> instance Monad ((,) Bool)  Defined at x.hs:2:10
>> • In the expression: GHC.Base.$dm>> @((,) Bool)
>> In an equation for ‘>>’: (>>) = GHC.Base.$dm>> @((,) Bool)
>> In the instance declaration for ‘Monad ((,) Bool)’
>> 
>> 2  instance Monad ((,) Bool) where
>>  ^^^^^^^^^^^^^^^^
>>
>> [one more similar overlap error elided]
>>
>> But I could not find the
>>
>> instance Monoid a => Monad ((,) a)
>>
>> documented anywhere in the base package. Should I look harder? Or is
>> this instance accidentally leaking from GHC.Base?
>>
>> Eventually, through some experimenting I found that if I replace Bool
>> with Any, then the existing instance seems to do what I want.
>>
>> Cheers
>> Ben
>>
>> _______________________________________________
>> HaskellCafe mailing list
>> To (un)subscribe, modify options or view archives go to:
>> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
>> Only members subscribed via the mailman list are allowed to post.
>
> _______________________________________________
> HaskellCafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
> Only members subscribed via the mailman list are allowed to post.
 next part 
An HTML attachment was scrubbed...
URL:
From neil_mayhew at users.sourceforge.net Mon Aug 5 20:57:26 2019
From: neil_mayhew at users.sourceforge.net (Neil Mayhew)
Date: Mon, 5 Aug 2019 14:57:26 0600
Subject: [Haskellcafe] instance Monoid a => Monad ((,) a)
InReplyTo:
References:
MessageID: <942a6ac0971d9099adecfafe95c73cfd@users.sourceforge.net>
On 20190805 2:33 p.m., Jinxuan Zhu wrote:
… Bool can be monoid by either  or && operations, which would lead
to ambiguity if Bool is monoid by default.
You can:
1. use Maybe Unit instead
2. (overkill) Define AndMonoid Bool newtype and use DeriveVia and
coerce
Data.Monoid from base already has Any and All for this.
 next part 
An HTML attachment was scrubbed...
URL:
From oleg.grenrus at iki.fi Tue Aug 6 09:03:55 2019
From: oleg.grenrus at iki.fi (Oleg Grenrus)
Date: Tue, 6 Aug 2019 12:03:55 +0300
Subject: [Haskellcafe] instance Monoid a => Monad ((,) a)
InReplyTo:
References:
MessageID:
There are All and Any Monoids in Data.Monoid
Sent from my iPhone
> On 5 Aug 2019, at 23.33, Jinxuan Zhu wrote:
>
> Hi, I think the error message says there is no Monoid for Bool. It is because Bool can be monoid by either  or && operations, which would lead to ambiguity if Bool is monoid by default.
>
> You can:
> 1. use Maybe Unit instead
> 2. (overkill) Define AndMonoid Bool newtype and use DeriveVia and coerce
>
>
>
>> On Fri, Aug 2, 2019 at 7:39 PM Benjamin Franksen wrote:
>> I wanted to define a simple Monad instance for (Bool,) as
>>
>> instance Monad ((,) Bool) where
>> return x = (False, x)
>> (True, x) >>= k = (True, snd (k x))
>> (False, x) >>= k = k x
>>  or: (b, x) >>= k = let (c, y) = k x in (bc, y)
>>
>> The idea was to keep track of whether functions change their input value
>> or not.
>>
>> To my astonishment I found that this definition overlaps with an
>> existing one. GHC tells me
>>
>> x.hs:2:10: error:
>> • No instance for (Monoid Bool)
>> arising from the superclasses of an instance declaration
>> • In the instance declaration for ‘Monad ((,) Bool)’
>> 
>> 2  instance Monad ((,) Bool) where
>>  ^^^^^^^^^^^^^^^^
>>
>> x.hs:2:10: error:
>> • Overlapping instances for Monad ((,) Bool)
>> arising from a use of ‘GHC.Base.$dm>>’
>> Matching instances:
>> instance Monoid a => Monad ((,) a)  Defined in ‘GHC.Base’
>> instance Monad ((,) Bool)  Defined at x.hs:2:10
>> • In the expression: GHC.Base.$dm>> @((,) Bool)
>> In an equation for ‘>>’: (>>) = GHC.Base.$dm>> @((,) Bool)
>> In the instance declaration for ‘Monad ((,) Bool)’
>> 
>> 2  instance Monad ((,) Bool) where
>>  ^^^^^^^^^^^^^^^^
>>
>> [one more similar overlap error elided]
>>
>> But I could not find the
>>
>> instance Monoid a => Monad ((,) a)
>>
>> documented anywhere in the base package. Should I look harder? Or is
>> this instance accidentally leaking from GHC.Base?
>>
>> Eventually, through some experimenting I found that if I replace Bool
>> with Any, then the existing instance seems to do what I want.
>>
>> Cheers
>> Ben
>>
>> _______________________________________________
>> HaskellCafe mailing list
>> To (un)subscribe, modify options or view archives go to:
>> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
>> Only members subscribed via the mailman list are allowed to post.
> _______________________________________________
> HaskellCafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
> Only members subscribed via the mailman list are allowed to post.
 next part 
An HTML attachment was scrubbed...
URL:
From tomlistshaskellcafe2017 at jaguarpaw.co.uk Tue Aug 6 12:15:01 2019
From: tomlistshaskellcafe2017 at jaguarpaw.co.uk (Tom Ellis)
Date: Tue, 6 Aug 2019 13:15:01 +0100
Subject: [Haskellcafe] instance Monoid a => Monad ((,) a)
InReplyTo:
References:
MessageID: <20190806121501.ckkvujdqwd7d5qta@weber>
When this question came up the other day I started to wonder how many
boolean operators are monoidal. I wrote a program to check.
There are eight associative operators (i.e. that give rise to semigroups).
They are
const True
or
const
flip const
xnor
and
xor
const False
Only four of these have an identity (i.e. give rise to monoids). They are
or
xnor
and
xor
Tom
> putStrLn showMonoids
Semigroups
TT=T TF=T FT=T FF=T
TT=T TF=T FT=T FF=F
TT=T TF=T FT=F FF=F
TT=T TF=F FT=T FF=F
TT=T TF=F FT=F FF=T
TT=T TF=F FT=F FF=F
TT=F TF=T FT=T FF=F
TT=F TF=F FT=F FF=F
Monoids
TT=T TF=T FT=T FF=F
TT=T TF=F FT=F FF=T
TT=T TF=F FT=F FF=F
TT=F TF=T FT=T FF=F
allOfThem :: [Bool]
allOfThem = [True, False]
binops :: [Bool > Bool > Bool]
binops = do
tt < allOfThem
tf < allOfThem
ft < allOfThem
ff < allOfThem
let f True True = tt
f True False = tf
f False True = ft
f False False = ff
pure f
associative :: (Bool > Bool > Bool) > Bool
associative (.*) = and $ do
x < allOfThem
y < allOfThem
z < allOfThem
pure (x .* (y .* z) == (x .* y) .* z)
identity :: (Bool > Bool > Bool) > Bool
identity (.*) = or $ do
i < allOfThem
return (and $ do
x < allOfThem
[x .* i == x, i .* x == x])
semigroups :: [Bool > Bool > Bool]
semigroups = filter associative binops
monoids :: [Bool > Bool > Bool]
monoids = filter identity semigroups
showBool :: Bool > String
showBool True = "T"
showBool False = "F"
showBinop :: (Bool > Bool > Bool) > String
showBinop (.*) = unwords $ do
x < allOfThem
y < allOfThem
pure (showBool x ++ showBool y ++ "=" ++ showBool (x .* y))
showMonoids :: String
showMonoids = (unlines . concat) [
["Semigroups"]
, map showBinop semigroups
, ["Monoids"]
, map showBinop monoids
]
On Mon, Aug 05, 2019 at 04:49:41PM 0400, David Feuer wrote:
> Bool is also a monoid under xor.
>
> On Mon, Aug 5, 2019, 4:34 PM Jinxuan Zhu wrote:
>
> > Hi, I think the error message says there is no Monoid for Bool. It is
> > because Bool can be monoid by either  or && operations, which would lead
> > to ambiguity if Bool is monoid by default.
> >
> > You can:
> > 1. use Maybe Unit instead
> > 2. (overkill) Define AndMonoid Bool newtype and use DeriveVia and coerce
> >
> > On Fri, Aug 2, 2019 at 7:39 PM Benjamin Franksen
> > wrote:
> >
> >> I wanted to define a simple Monad instance for (Bool,) as
> >>
> >> instance Monad ((,) Bool) where
> >> return x = (False, x)
> >> (True, x) >>= k = (True, snd (k x))
> >> (False, x) >>= k = k x
> >>  or: (b, x) >>= k = let (c, y) = k x in (bc, y)
> >>
> >> The idea was to keep track of whether functions change their input value
> >> or not.
> >>
> >> To my astonishment I found that this definition overlaps with an
> >> existing one. GHC tells me
> >>
> >> x.hs:2:10: error:
> >> • No instance for (Monoid Bool)
> >> arising from the superclasses of an instance declaration
> >> • In the instance declaration for ‘Monad ((,) Bool)’
> >> 
> >> 2  instance Monad ((,) Bool) where
> >>  ^^^^^^^^^^^^^^^^
> >>
> >> x.hs:2:10: error:
> >> • Overlapping instances for Monad ((,) Bool)
> >> arising from a use of ‘GHC.Base.$dm>>’
> >> Matching instances:
> >> instance Monoid a => Monad ((,) a)  Defined in ‘GHC.Base’
> >> instance Monad ((,) Bool)  Defined at x.hs:2:10
> >> • In the expression: GHC.Base.$dm>> @((,) Bool)
> >> In an equation for ‘>>’: (>>) = GHC.Base.$dm>> @((,) Bool)
> >> In the instance declaration for ‘Monad ((,) Bool)’
> >> 
> >> 2  instance Monad ((,) Bool) where
> >>  ^^^^^^^^^^^^^^^^
> >>
> >> [one more similar overlap error elided]
> >>
> >> But I could not find the
> >>
> >> instance Monoid a => Monad ((,) a)
> >>
> >> documented anywhere in the base package. Should I look harder? Or is
> >> this instance accidentally leaking from GHC.Base?
> >>
> >> Eventually, through some experimenting I found that if I replace Bool
> >> with Any, then the existing instance seems to do what I want.
From hjgtuyl at chello.nl Wed Aug 7 00:11:42 2019
From: hjgtuyl at chello.nl (HenkJan van Tuyl)
Date: Wed, 07 Aug 2019 02:11:42 +0200
Subject: [Haskellcafe] cabal: Could not resolve dependencies
MessageID:
L.S.,
I am trying to compile wxHaskell with GHC 8.8.0.20190721 and I get the
following messages from cabalinstall:
> cabal newbuild all disabledocumentation
Resolving dependencies...
cabal: Could not resolve dependencies:
[__0] trying: samplesContrib0.93.0.0 (user goal)
[__1] trying: base4.13.0.0/installed4.1... (dependency of samplesContrib)
[__2] trying: wxcore0.93.0.0 (user goal)
[__3] next goal: wxcore:setup.Cabal (dependency of wxcore)
[__3] rejecting: wxcore:setup.Cabal3.0.0.0/installed3.0... (constraint
from
maximum version of Cabal used by Setup.hs requires <2.6
[...]
What does this mean, how do I solve it?
(There is a Setup.hs in package wxcore, but does it have its own Cabal
file?)
> cabal version
cabalinstall version 2.4.1.0
compiled using version 2.4.1.0 of the Cabal library
Regards,
HenkJan van Tuyl

Message from Stanford University:
Folding at home
What if you could share your unused computer power to help find a cure? In
just 5 minutes you can join the world's biggest networked computer and get
us closer sooner. Watch the video.
http://foldingathome.stanford.edu/

http://members.chello.nl/hjgtuyl/tourdemonad.html
Haskell programming

From vamchale at gmail.com Wed Aug 7 02:03:23 2019
From: vamchale at gmail.com (Vanessa McHale)
Date: Tue, 6 Aug 2019 21:03:23 0500
Subject: [Haskellcafe] cabal: Could not resolve dependencies
InReplyTo:
References:
MessageID:
Is there a reason you're using GHC 8.8.1?
This means that wxcore uses a custom setup, and that custom setup
requires Cabal <2.6. But you can't use Cabal 2.4 because that requires
base <4.13
Cheers,
Vanessa McHale
On 8/6/19 7:11 PM, HenkJan van Tuyl wrote:
>
> L.S.,
>
> I am trying to compile wxHaskell with GHC 8.8.0.20190721 and I get the
> following messages from cabalinstall:
>
>> cabal newbuild all disabledocumentation
> Resolving dependencies...
> cabal: Could not resolve dependencies:
> [__0] trying: samplesContrib0.93.0.0 (user goal)
> [__1] trying: base4.13.0.0/installed4.1... (dependency of
> samplesContrib)
> [__2] trying: wxcore0.93.0.0 (user goal)
> [__3] next goal: wxcore:setup.Cabal (dependency of wxcore)
> [__3] rejecting: wxcore:setup.Cabal3.0.0.0/installed3.0...
> (constraint from
> maximum version of Cabal used by Setup.hs requires <2.6
> [...]
>
> What does this mean, how do I solve it?
> (There is a Setup.hs in package wxcore, but does it have its own Cabal
> file?)
>
>> cabal version
> cabalinstall version 2.4.1.0
> compiled using version 2.4.1.0 of the Cabal library
>
> Regards,
> HenkJan van Tuyl
>
>
 next part 
A nontext attachment was scrubbed...
Name: signature.asc
Type: application/pgpsignature
Size: 659 bytes
Desc: OpenPGP digital signature
URL:
From hilco.wijbenga at gmail.com Wed Aug 7 03:28:34 2019
From: hilco.wijbenga at gmail.com (Hilco Wijbenga)
Date: Tue, 6 Aug 2019 20:28:34 0700
Subject: [Haskellcafe] Evaluating an AST with GADTs (and Type Families?)
MessageID:
Hi all,
I'm trying to implement an evaluator with GADTs. This is about as far
as I've gotten: https://pastebin.com/XjWBzgw7 .
data Value
= ValueBool Bool
 ValueText String
 ValueObject (Map String Value)
data Expr t where
ExprBool :: Bool > Expr Bool
ExprBoolOr :: Expr Bool > Expr Bool > Expr Bool
ExprText :: String > Expr String
ExprTextAppend :: Expr String > Expr String > Expr String
ExprObject :: Map String Value > String > Expr Value
eval :: Expr t > t
eval (ExprBool value) = value
eval (ExprBoolOr lft rgt) = eval lft  eval rgt
eval (ExprText value) = value
eval (ExprTextAppend lft rgt) = eval lft <> eval rgt
eval (ExprObject map fieldName) = map ! fieldName
Note that the Value data type was just an attempt and not
(necessarily) what I'm looking for. And I'm ignoring all error
handling for the moment to keep the example small.
This compiles but obviously the object type is completely separate
from the Expr Bool and Expr String types. Apparently, Type Familiies
might help here? I could not find anything relevant that really
explained it.
I've been thinking about changing ExprObject to something like
ExprObjectBool :: Map String Value > String > Expr Bool
ExprObjectString :: Map String Value > String > Expr String
ExprObjectObject :: Map String Value > String > Expr ???
but I can't figure out what ??? would be. And this would seem to
explode if I add more "primitive" types, especially if I want to
support lists and maps as well. (Maps and objects are very similar but
not the same.)
How would I go about making the object type useful here? Or should I
go back to plain "Expr" and just error out when trying to, e.g., "or"
2 Strings?
Cheers,
Hilco
From 78emil at gmail.com Wed Aug 7 08:35:08 2019
From: 78emil at gmail.com (Emil Axelsson)
Date: Wed, 7 Aug 2019 10:35:08 +0200
Subject: [Haskellcafe] Evaluating an AST with GADTs (and Type Families?)
InReplyTo:
References:
MessageID:
Hi!
I would just skip the `Value` type and go with this
type Object = Map String
data Expr t where
ExprBool :: Bool > Expr Bool
ExprBoolOr :: Expr Bool > Expr Bool > Expr Bool
ExprText :: String > Expr String
ExprTextAppend :: Expr String > Expr String > Expr String
ExprObject :: Object (Expr t) > Expr (Object t)
ExprLookup :: Expr (Object t) > String > Expr t
eval :: Expr t > t
eval (ExprBool value) = value
eval (ExprBoolOr lft rgt) = eval lft  eval rgt
eval (ExprText value) = value
eval (ExprTextAppend lft rgt) = eval lft <> eval rgt
eval (ExprObject map) = eval <$> map
eval (ExprLookup map fieldName) = eval map ! fieldName
`ExprObject` constructs an object expression from a mapping that has
expressions in the range.
`ExprLookup` looks up a field name from an object expression.
This is more general, because it lets you have expressions of arbitrary
type in objects. But it gets harder if you need to restrict the types
that can appear in objects.
/ Emil
Den 20190807 kl. 05:28, skrev Hilco Wijbenga:
> Hi all,
>
> I'm trying to implement an evaluator with GADTs. This is about as far
> as I've gotten: https://pastebin.com/XjWBzgw7 .
>
> data Value
> = ValueBool Bool
>  ValueText String
>  ValueObject (Map String Value)
>
> data Expr t where
> ExprBool :: Bool > Expr Bool
> ExprBoolOr :: Expr Bool > Expr Bool > Expr Bool
> ExprText :: String > Expr String
> ExprTextAppend :: Expr String > Expr String > Expr String
> ExprObject :: Map String Value > String > Expr Value
>
> eval :: Expr t > t
> eval (ExprBool value) = value
> eval (ExprBoolOr lft rgt) = eval lft  eval rgt
> eval (ExprText value) = value
> eval (ExprTextAppend lft rgt) = eval lft <> eval rgt
> eval (ExprObject map fieldName) = map ! fieldName
>
> Note that the Value data type was just an attempt and not
> (necessarily) what I'm looking for. And I'm ignoring all error
> handling for the moment to keep the example small.
>
> This compiles but obviously the object type is completely separate
> from the Expr Bool and Expr String types. Apparently, Type Familiies
> might help here? I could not find anything relevant that really
> explained it.
>
> I've been thinking about changing ExprObject to something like
>
> ExprObjectBool :: Map String Value > String > Expr Bool
> ExprObjectString :: Map String Value > String > Expr String
> ExprObjectObject :: Map String Value > String > Expr ???
>
> but I can't figure out what ??? would be. And this would seem to
> explode if I add more "primitive" types, especially if I want to
> support lists and maps as well. (Maps and objects are very similar but
> not the same.)
>
> How would I go about making the object type useful here? Or should I
> go back to plain "Expr" and just error out when trying to, e.g., "or"
> 2 Strings?
>
> Cheers,
> Hilco
> _______________________________________________
> HaskellCafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
> Only members subscribed via the mailman list are allowed to post.
From kolar at fit.vut.cz Wed Aug 7 09:52:35 2019
From: kolar at fit.vut.cz (=?utf8?B?RHXFoWFuIEtvbMOhxZk=?=)
Date: Wed, 07 Aug 2019 11:52:35 +0200
Subject: [Haskellcafe] Ambiguous types
MessageID: <2162795.o9Qe6PU3hX@pckolar>
Dear Café,
I'm trying to solve a couple of examples and exercises just for me. I've
come to the point, when I'm trying working code manipulating lists rewrite to work
on Foldable (etc.).
Nevertheless, I must be doing some mistake, overlooking something, as
simple code like this:
chkDup [] = False
chkDup (0:ns) = chkDup ns
chkDup (n:ns) = elem n ns  chkDup ns
which works fine, typechecks, can be used within other code, I'm trying to replace
with more generic, but probably less efficient and wrong code:
chkDup ns = fst $ foldr f (False,mempty) ns
where
f _ res@(True,_) = res
f v res@(_,vs) = if v==0 then (False, vs) else (elem v vs, pure v <> vs)
which does not even typecheck.
Nevertheless, the error message is not too helpful, searching the Internet just
confirms it's wrong and that adding AllowAmbiguousTypes would not work. The
error message is:
helper.hs:49:1: error:
• Could not deduce (Foldable f0)
from the context: (Eq a, Num a, Foldable t, Foldable f,
Applicative f, Monoid (f a))
bound by the inferred type for ‘chkDup’:
forall a (t :: * > *) (f :: * > *).
(Eq a, Num a, Foldable t, Foldable f, Applicative f,
Monoid (f a)) =>
t a > Bool
at helper.hs:(49,1)(53,80)
The type variable ‘f0’ is ambiguous
• In the ambiguity check for the inferred type for ‘chkDup’
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
When checking the inferred type
chkDup :: forall a (t :: * > *) (f :: * > *).
(Eq a, Num a, Foldable t, Foldable f, Applicative f,
Monoid (f a)) =>
t a > Bool

49  chkDup ns =
 ^^^^^^^^^^^...
So is there a nicer and working way, how to change my simple example? Is there a
way, how to make it compile? Or is it useless to do that, original function is just
fine...
Best regards,
Dušan
 next part 
An HTML attachment was scrubbed...
URL:
From paolo.veronelli at gmail.com Wed Aug 7 11:05:39 2019
From: paolo.veronelli at gmail.com (Paolino)
Date: Wed, 7 Aug 2019 13:05:39 +0200
Subject: [Haskellcafe] Ambiguous types
InReplyTo: <2162795.o9Qe6PU3hX@pckolar>
References: <2162795.o9Qe6PU3hX@pckolar>
MessageID:
So about the type error, the second element of the tuple has no defined
type. You can fix it substituting (pure v) with [v] if you want a list
there.
Also
 chkDup ns = any (`elem` ns)
 use Set.member to reduce complexity
Best
On Wed, 7 Aug 2019 at 11:53, Dušan Kolář wrote:
> Dear Café,
>
>
>
> I'm trying to solve a couple of examples and exercises just for me. I've
> come to the point, when I'm trying working code manipulating lists rewrite
> to work on Foldable (etc.).
>
>
>
> Nevertheless, I must be doing some mistake, overlooking something, as
> simple code like this:
>
>
>
> chkDup [] = False
>
> chkDup (0:ns) = chkDup ns
>
> chkDup (n:ns) = elem n ns  chkDup ns
>
>
>
> which works fine, typechecks, can be used within other code, I'm trying
> to replace with more generic, but probably less efficient and wrong code:
>
>
>
> chkDup ns = fst $ foldr f (False,mempty) ns
>
> where
>
> f _ res@(True,_) = res
>
> f v res@(_,vs) = if v==0 then (False, vs) else (elem v vs, pure v <> vs)
>
>
>
> which does not even typecheck.
>
>
>
> Nevertheless, the error message is not too helpful, searching the Internet
> just confirms it's wrong and that adding AllowAmbiguousTypes would not
> work. The error message is:
>
>
>
> helper.hs:49:1: error:
>
> • Could not deduce (Foldable f0)
>
> from the context: (Eq a, Num a, Foldable t, Foldable f,
>
> Applicative f, Monoid (f a))
>
> bound by the inferred type for ‘chkDup’:
>
> forall a (t :: * > *) (f :: * > *).
>
> (Eq a, Num a, Foldable t, Foldable f, Applicative f,
>
> Monoid (f a)) =>
>
> t a > Bool
>
> at helper.hs:(49,1)(53,80)
>
> The type variable ‘f0’ is ambiguous
>
> • In the ambiguity check for the inferred type for ‘chkDup’
>
> To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
>
> When checking the inferred type
>
> chkDup :: forall a (t :: * > *) (f :: * > *).
>
> (Eq a, Num a, Foldable t, Foldable f, Applicative f,
>
> Monoid (f a)) =>
>
> t a > Bool
>
> 
>
> 49  chkDup ns =
>
>  ^^^^^^^^^^^...
>
>
>
>
>
> So is there a nicer and working way, how to change my simple example? Is
> there a way, how to make it compile? Or is it useless to do that, original
> function is just fine...
>
>
>
> Best regards,
>
> Dušan
>
>
> _______________________________________________
> HaskellCafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
> Only members subscribed via the mailman list are allowed to post.

Paolo Veronelli (paolo.veronelli at gmail.com)
*Functional developer @ global.de *
 next part 
An HTML attachment was scrubbed...
URL:
From paolo.veronelli at gmail.com Wed Aug 7 11:13:32 2019
From: paolo.veronelli at gmail.com (Paolino)
Date: Wed, 7 Aug 2019 13:13:32 +0200
Subject: [Haskellcafe] Ambiguous types
InReplyTo:
References: <2162795.o9Qe6PU3hX@pckolar>
MessageID:
Pardon, delete my code. I rushed the answer without reading carefully, my
bad.
On Wed, 7 Aug 2019 at 13:05, Paolino wrote:
> So about the type error, the second element of the tuple has no defined
> type. You can fix it substituting (pure v) with [v] if you want a list
> there.
>
> Also
>
>  chkDup ns = any (`elem` ns)
>  use Set.member to reduce complexity
>
> Best
>
> On Wed, 7 Aug 2019 at 11:53, Dušan Kolář wrote:
>
>> Dear Café,
>>
>>
>>
>> I'm trying to solve a couple of examples and exercises just for me. I've
>> come to the point, when I'm trying working code manipulating lists rewrite
>> to work on Foldable (etc.).
>>
>>
>>
>> Nevertheless, I must be doing some mistake, overlooking something, as
>> simple code like this:
>>
>>
>>
>> chkDup [] = False
>>
>> chkDup (0:ns) = chkDup ns
>>
>> chkDup (n:ns) = elem n ns  chkDup ns
>>
>>
>>
>> which works fine, typechecks, can be used within other code, I'm trying
>> to replace with more generic, but probably less efficient and wrong code:
>>
>>
>>
>> chkDup ns = fst $ foldr f (False,mempty) ns
>>
>> where
>>
>> f _ res@(True,_) = res
>>
>> f v res@(_,vs) = if v==0 then (False, vs) else (elem v vs, pure v <> vs)
>>
>>
>>
>> which does not even typecheck.
>>
>>
>>
>> Nevertheless, the error message is not too helpful, searching the
>> Internet just confirms it's wrong and that adding AllowAmbiguousTypes would
>> not work. The error message is:
>>
>>
>>
>> helper.hs:49:1: error:
>>
>> • Could not deduce (Foldable f0)
>>
>> from the context: (Eq a, Num a, Foldable t, Foldable f,
>>
>> Applicative f, Monoid (f a))
>>
>> bound by the inferred type for ‘chkDup’:
>>
>> forall a (t :: * > *) (f :: * > *).
>>
>> (Eq a, Num a, Foldable t, Foldable f, Applicative f,
>>
>> Monoid (f a)) =>
>>
>> t a > Bool
>>
>> at helper.hs:(49,1)(53,80)
>>
>> The type variable ‘f0’ is ambiguous
>>
>> • In the ambiguity check for the inferred type for ‘chkDup’
>>
>> To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
>>
>> When checking the inferred type
>>
>> chkDup :: forall a (t :: * > *) (f :: * > *).
>>
>> (Eq a, Num a, Foldable t, Foldable f, Applicative f,
>>
>> Monoid (f a)) =>
>>
>> t a > Bool
>>
>> 
>>
>> 49  chkDup ns =
>>
>>  ^^^^^^^^^^^...
>>
>>
>>
>>
>>
>> So is there a nicer and working way, how to change my simple example? Is
>> there a way, how to make it compile? Or is it useless to do that, original
>> function is just fine...
>>
>>
>>
>> Best regards,
>>
>> Dušan
>>
>>
>> _______________________________________________
>> HaskellCafe mailing list
>> To (un)subscribe, modify options or view archives go to:
>> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
>> Only members subscribed via the mailman list are allowed to post.
>
>
>
> 
>
> Paolo Veronelli (paolo.veronelli at gmail.com)
>
>
> *Functional developer @ global.de *
>
>

Paolo Veronelli (paolo.veronelli at gmail.com)
*Functional developer @ global.de *
 next part 
An HTML attachment was scrubbed...
URL:
From juan.casanova at ed.ac.uk Wed Aug 7 11:17:27 2019
From: juan.casanova at ed.ac.uk (Juan Casanova)
Date: Wed, 07 Aug 2019 12:17:27 +0100
Subject: [Haskellcafe] Ambiguous types
InReplyTo:
References: <2162795.o9Qe6PU3hX@pckolar>
MessageID: <20190807121727.18661n6493o30sis@www.staffmail.ed.ac.uk>
To build up on Paolino's answer, and maybe, if you're like me, give
you a better intuition as to why your code was incorrect, but leading
to essentially the same answer he gave.
First, you didn't provide us with the type signatures for chkDup and
f, but I worked with the following ones to start with:
chkDup :: forall a (t :: * > *) (f :: * > *). (Eq a, Num a, Foldable
t, Foldable f, Applicative f, Monoid (f a)) => t a > Bool
f :: (Num a, Foldable t, Semigroup (t a), Applicative t, Eq a) => a >
(Bool, t a) > (Bool, t a)
This gives me the same error you get even if I define chkDup _ = undefined.
The problem is that you are providing class constraints for the type
f, which does not appear at all in the signature of the function (t a
> Bool), and this makes the typechecker get super confused. Now, I
know why you thought this was necessary: precisely because of what
Paolino pointed out: mempty has an undefined type, and you tried to
fix this by saying "This mempty is of type f, which I don't care for
the type, just that it is a Semigroup and Applicative". But this is a
mistake. So, if you just remove the f altogether from the class
constraints of the chkDup type signature, and leave it like this:
chkDup :: forall a (t :: * > *) (f :: * > *). (Eq a, Num a, Foldable
t) => t a > Bool
You still get an error, but now you get the actual error message that
you're looking for: "Could not deduce Foldable t0 arising from a use
of f".
The right way to fix this is how Paolino said: Specify what Foldable
you're going to use (recommended: list) (so, use [] instead of
mempty). The point is, since the type f is not part of the input NOR
the output of the function chkDup, and instead it is just an internal
tool that you use to compute chkDup, there's no reason to want to be
generic about it, there's no advantage in that. The advantage in
genericity using typeclasses is: 1. If it's in the input, you allow
the user of the function to provide you with any type that fulfills
the class. 2. You make it very clear that everything you do with that
parameter is related to its typeclass instance, as there is no way to
inspect the actual type. 3. If it's in the output, you don't let users
of the function make any assumption of what that type might look like,
other than its typeclass instance.
But in an internal tool that doesn't come from outside and isn't
output by your function, there's no reason to be generic, just use
lists. The only reason I could see being argued for wanting to be
generic would be if you'd like the user to provide you with hints as
to how to compute the function so that it's more efficient. If you
really want to go that far, I think there's other ways to do that,
that I haven't thought of right now.
All in all, the following code works:
chkDup :: forall a (t :: * > *) (f :: * > *). (Eq a, Num a, Foldable
t) => t a > Bool
chkDup ns = fst $ foldr f (False,[]) ns
f :: (Num a, Foldable t, Semigroup (t a), Applicative t, Eq a) => a >
(Bool, t a) > (Bool, t a)
f _ res@(True,_) = res
f v res@(_,vs) = if v==0 then (False, vs) else (elem v vs, pure v <> vs)
I hope you found that useful.
Juan.
Quoting Paolino on Wed, 7 Aug 2019 13:05:39 +0200:
> So about the type error, the second element of the tuple has no defined
> type. You can fix it substituting (pure v) with [v] if you want a list
> there.
>
> Also
>
>  chkDup ns = any (`elem` ns)
>  use Set.member to reduce complexity
>
> Best
>
> On Wed, 7 Aug 2019 at 11:53, Dušan Kolář wrote:
>
>> Dear Café,
>>
>>
>>
>> I'm trying to solve a couple of examples and exercises just for me. I've
>> come to the point, when I'm trying working code manipulating lists rewrite
>> to work on Foldable (etc.).
>>
>>
>>
>> Nevertheless, I must be doing some mistake, overlooking something, as
>> simple code like this:
>>
>>
>>
>> chkDup [] = False
>>
>> chkDup (0:ns) = chkDup ns
>>
>> chkDup (n:ns) = elem n ns  chkDup ns
>>
>>
>>
>> which works fine, typechecks, can be used within other code, I'm trying
>> to replace with more generic, but probably less efficient and wrong code:
>>
>>
>>
>> chkDup ns = fst $ foldr f (False,mempty) ns
>>
>> where
>>
>> f _ res@(True,_) = res
>>
>> f v res@(_,vs) = if v==0 then (False, vs) else (elem v vs, pure v <> vs)
>>
>>
>>
>> which does not even typecheck.
>>
>>
>>
>> Nevertheless, the error message is not too helpful, searching the Internet
>> just confirms it's wrong and that adding AllowAmbiguousTypes would not
>> work. The error message is:
>>
>>
>>
>> helper.hs:49:1: error:
>>
>> • Could not deduce (Foldable f0)
>>
>> from the context: (Eq a, Num a, Foldable t, Foldable f,
>>
>> Applicative f, Monoid (f a))
>>
>> bound by the inferred type for ‘chkDup’:
>>
>> forall a (t :: * > *) (f :: * > *).
>>
>> (Eq a, Num a, Foldable t, Foldable f, Applicative f,
>>
>> Monoid (f a)) =>
>>
>> t a > Bool
>>
>> at helper.hs:(49,1)(53,80)
>>
>> The type variable ‘f0’ is ambiguous
>>
>> • In the ambiguity check for the inferred type for ‘chkDup’
>>
>> To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
>>
>> When checking the inferred type
>>
>> chkDup :: forall a (t :: * > *) (f :: * > *).
>>
>> (Eq a, Num a, Foldable t, Foldable f, Applicative f,
>>
>> Monoid (f a)) =>
>>
>> t a > Bool
>>
>> 
>>
>> 49  chkDup ns =
>>
>>  ^^^^^^^^^^^...
>>
>>
>>
>>
>>
>> So is there a nicer and working way, how to change my simple example? Is
>> there a way, how to make it compile? Or is it useless to do that, original
>> function is just fine...
>>
>>
>>
>> Best regards,
>>
>> Dušan
>>
>>
>> _______________________________________________
>> HaskellCafe mailing list
>> To (un)subscribe, modify options or view archives go to:
>> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
>> Only members subscribed via the mailman list are allowed to post.
>
>
>
> 
>
> Paolo Veronelli (paolo.veronelli at gmail.com)
>
>
> *Functional developer @ global.de *
>

The University of Edinburgh is a charitable body, registered in
Scotland, with registration number SC005336.
From juan.casanova at ed.ac.uk Wed Aug 7 11:21:27 2019
From: juan.casanova at ed.ac.uk (Juan Casanova)
Date: Wed, 07 Aug 2019 12:21:27 +0100
Subject: [Haskellcafe] Ambiguous types
InReplyTo: <20190807121727.18661n6493o30sis@www.staffmail.ed.ac.uk>
References: <2162795.o9Qe6PU3hX@pckolar>
<20190807121727.18661n6493o30sis@www.staffmail.ed.ac.uk>
MessageID: <20190807122127.14952dhisipgjr6s@www.staffmail.ed.ac.uk>
PS: I didn't even spend much time thinking how I would probably
implement chkDup differently even for the generic case that you want
to do. As in, intuition tells me you don't really need an applicative
monoid internally to do what you're trying to do. But, as I said,
haven't thought it thoroughly, and with the code I gave you, you get
what you were trying to do and it's not "wrong". Maybe just overkill.
Quoting Juan Casanova on Wed, 07 Aug 2019
12:17:27 +0100:
> To build up on Paolino's answer, and maybe, if you're like me, give
> you a better intuition as to why your code was incorrect, but
> leading to essentially the same answer he gave.
>
> First, you didn't provide us with the type signatures for chkDup and
> f, but I worked with the following ones to start with:
>
> chkDup :: forall a (t :: * > *) (f :: * > *). (Eq a, Num a,
> Foldable t, Foldable f, Applicative f, Monoid (f a)) => t a > Bool
>
> f :: (Num a, Foldable t, Semigroup (t a), Applicative t, Eq a) => a
> > (Bool, t a) > (Bool, t a)
>
> This gives me the same error you get even if I define chkDup _ = undefined.
>
> The problem is that you are providing class constraints for the type
> f, which does not appear at all in the signature of the function (t
> a > Bool), and this makes the typechecker get super confused. Now,
> I know why you thought this was necessary: precisely because of what
> Paolino pointed out: mempty has an undefined type, and you tried to
> fix this by saying "This mempty is of type f, which I don't care for
> the type, just that it is a Semigroup and Applicative". But this is
> a mistake. So, if you just remove the f altogether from the class
> constraints of the chkDup type signature, and leave it like this:
>
> chkDup :: forall a (t :: * > *) (f :: * > *). (Eq a, Num a,
> Foldable t) => t a > Bool
>
> You still get an error, but now you get the actual error message
> that you're looking for: "Could not deduce Foldable t0 arising from
> a use of f".
>
> The right way to fix this is how Paolino said: Specify what Foldable
> you're going to use (recommended: list) (so, use [] instead of
> mempty). The point is, since the type f is not part of the input NOR
> the output of the function chkDup, and instead it is just an
> internal tool that you use to compute chkDup, there's no reason to
> want to be generic about it, there's no advantage in that. The
> advantage in genericity using typeclasses is: 1. If it's in the
> input, you allow the user of the function to provide you with any
> type that fulfills the class. 2. You make it very clear that
> everything you do with that parameter is related to its typeclass
> instance, as there is no way to inspect the actual type. 3. If it's
> in the output, you don't let users of the function make any
> assumption of what that type might look like, other than its
> typeclass instance.
>
> But in an internal tool that doesn't come from outside and isn't
> output by your function, there's no reason to be generic, just use
> lists. The only reason I could see being argued for wanting to be
> generic would be if you'd like the user to provide you with hints as
> to how to compute the function so that it's more efficient. If you
> really want to go that far, I think there's other ways to do that,
> that I haven't thought of right now.
>
> All in all, the following code works:
>
> chkDup :: forall a (t :: * > *) (f :: * > *). (Eq a, Num a,
> Foldable t) => t a > Bool
> chkDup ns = fst $ foldr f (False,[]) ns
>
> f :: (Num a, Foldable t, Semigroup (t a), Applicative t, Eq a) => a
> > (Bool, t a) > (Bool, t a)
> f _ res@(True,_) = res
> f v res@(_,vs) = if v==0 then (False, vs) else (elem v vs, pure v <> vs)
>
> I hope you found that useful.
>
> Juan.
>
> Quoting Paolino on Wed, 7 Aug 2019
> 13:05:39 +0200:
>
>> So about the type error, the second element of the tuple has no defined
>> type. You can fix it substituting (pure v) with [v] if you want a list
>> there.
>>
>> Also
>>
>>  chkDup ns = any (`elem` ns)
>>  use Set.member to reduce complexity
>>
>> Best
>>
>> On Wed, 7 Aug 2019 at 11:53, Dušan Kolář wrote:
>>
>>> Dear Café,
>>>
>>>
>>>
>>> I'm trying to solve a couple of examples and exercises just for me. I've
>>> come to the point, when I'm trying working code manipulating lists rewrite
>>> to work on Foldable (etc.).
>>>
>>>
>>>
>>> Nevertheless, I must be doing some mistake, overlooking something, as
>>> simple code like this:
>>>
>>>
>>>
>>> chkDup [] = False
>>>
>>> chkDup (0:ns) = chkDup ns
>>>
>>> chkDup (n:ns) = elem n ns  chkDup ns
>>>
>>>
>>>
>>> which works fine, typechecks, can be used within other code, I'm trying
>>> to replace with more generic, but probably less efficient and wrong code:
>>>
>>>
>>>
>>> chkDup ns = fst $ foldr f (False,mempty) ns
>>>
>>> where
>>>
>>> f _ res@(True,_) = res
>>>
>>> f v res@(_,vs) = if v==0 then (False, vs) else (elem v vs, pure v <> vs)
>>>
>>>
>>>
>>> which does not even typecheck.
>>>
>>>
>>>
>>> Nevertheless, the error message is not too helpful, searching the Internet
>>> just confirms it's wrong and that adding AllowAmbiguousTypes would not
>>> work. The error message is:
>>>
>>>
>>>
>>> helper.hs:49:1: error:
>>>
>>> • Could not deduce (Foldable f0)
>>>
>>> from the context: (Eq a, Num a, Foldable t, Foldable f,
>>>
>>> Applicative f, Monoid (f a))
>>>
>>> bound by the inferred type for ‘chkDup’:
>>>
>>> forall a (t :: * > *) (f :: * > *).
>>>
>>> (Eq a, Num a, Foldable t, Foldable f, Applicative f,
>>>
>>> Monoid (f a)) =>
>>>
>>> t a > Bool
>>>
>>> at helper.hs:(49,1)(53,80)
>>>
>>> The type variable ‘f0’ is ambiguous
>>>
>>> • In the ambiguity check for the inferred type for ‘chkDup’
>>>
>>> To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
>>>
>>> When checking the inferred type
>>>
>>> chkDup :: forall a (t :: * > *) (f :: * > *).
>>>
>>> (Eq a, Num a, Foldable t, Foldable f, Applicative f,
>>>
>>> Monoid (f a)) =>
>>>
>>> t a > Bool
>>>
>>> 
>>>
>>> 49  chkDup ns =
>>>
>>>  ^^^^^^^^^^^...
>>>
>>>
>>>
>>>
>>>
>>> So is there a nicer and working way, how to change my simple example? Is
>>> there a way, how to make it compile? Or is it useless to do that, original
>>> function is just fine...
>>>
>>>
>>>
>>> Best regards,
>>>
>>> Dušan
>>>
>>>
>>> _______________________________________________
>>> HaskellCafe mailing list
>>> To (un)subscribe, modify options or view archives go to:
>>> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
>>> Only members subscribed via the mailman list are allowed to post.
>>
>>
>>
>> 
>>
>> Paolo Veronelli (paolo.veronelli at gmail.com)
>>
>>
>> *Functional developer @ global.de *
>>
>
>
>
> 
> The University of Edinburgh is a charitable body, registered in
> Scotland, with registration number SC005336.
>
>
> _______________________________________________
> HaskellCafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
> Only members subscribed via the mailman list are allowed to post.

The University of Edinburgh is a charitable body, registered in
Scotland, with registration number SC005336.
From paolo.veronelli at gmail.com Wed Aug 7 11:37:53 2019
From: paolo.veronelli at gmail.com (Paolino)
Date: Wed, 7 Aug 2019 13:37:53 +0200
Subject: [Haskellcafe] Ambiguous types
InReplyTo:
References: <2162795.o9Qe6PU3hX@pckolar>
MessageID:
I will try again to repair my rushing on the code side
I'm interpreting that
[0,0,1] > False
[0,1,2,1] > True
To remove the explicit recursion, and noticing the 0 case
any (\(x:xs) > x `elem` xs) . init . tails . filter (/= 0)  quadratic
but exit soon
any identity . (zipWith (==) <*> tail) . sort . filter (/= 0)  n log n ,
but has to sort always
I'm not sure, what the other code should do with the accumulated part , as
it accumulates duplicates too and forget about the previous boolean
Hope I read it enough carefully now , to be helpful.
Best
On Wed, 7 Aug 2019 at 13:13, Paolino wrote:
> Pardon, delete my code. I rushed the answer without reading carefully, my
> bad.
>
>
> On Wed, 7 Aug 2019 at 13:05, Paolino wrote:
>
>> So about the type error, the second element of the tuple has no defined
>> type. You can fix it substituting (pure v) with [v] if you want a list
>> there.
>>
>> Also
>>
>>  chkDup ns = any (`elem` ns)
>>  use Set.member to reduce complexity
>>
>> Best
>>
>> On Wed, 7 Aug 2019 at 11:53, Dušan Kolář wrote:
>>
>>> Dear Café,
>>>
>>>
>>>
>>> I'm trying to solve a couple of examples and exercises just for me. I've
>>> come to the point, when I'm trying working code manipulating lists rewrite
>>> to work on Foldable (etc.).
>>>
>>>
>>>
>>> Nevertheless, I must be doing some mistake, overlooking something, as
>>> simple code like this:
>>>
>>>
>>>
>>> chkDup [] = False
>>>
>>> chkDup (0:ns) = chkDup ns
>>>
>>> chkDup (n:ns) = elem n ns  chkDup ns
>>>
>>>
>>>
>>> which works fine, typechecks, can be used within other code, I'm trying
>>> to replace with more generic, but probably less efficient and wrong code:
>>>
>>>
>>>
>>> chkDup ns = fst $ foldr f (False,mempty) ns
>>>
>>> where
>>>
>>> f _ res@(True,_) = res
>>>
>>> f v res@(_,vs) = if v==0 then (False, vs) else (elem v vs, pure v <> vs)
>>>
>>>
>>>
>>> which does not even typecheck.
>>>
>>>
>>>
>>> Nevertheless, the error message is not too helpful, searching the
>>> Internet just confirms it's wrong and that adding AllowAmbiguousTypes would
>>> not work. The error message is:
>>>
>>>
>>>
>>> helper.hs:49:1: error:
>>>
>>> • Could not deduce (Foldable f0)
>>>
>>> from the context: (Eq a, Num a, Foldable t, Foldable f,
>>>
>>> Applicative f, Monoid (f a))
>>>
>>> bound by the inferred type for ‘chkDup’:
>>>
>>> forall a (t :: * > *) (f :: * > *).
>>>
>>> (Eq a, Num a, Foldable t, Foldable f, Applicative f,
>>>
>>> Monoid (f a)) =>
>>>
>>> t a > Bool
>>>
>>> at helper.hs:(49,1)(53,80)
>>>
>>> The type variable ‘f0’ is ambiguous
>>>
>>> • In the ambiguity check for the inferred type for ‘chkDup’
>>>
>>> To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
>>>
>>> When checking the inferred type
>>>
>>> chkDup :: forall a (t :: * > *) (f :: * > *).
>>>
>>> (Eq a, Num a, Foldable t, Foldable f, Applicative f,
>>>
>>> Monoid (f a)) =>
>>>
>>> t a > Bool
>>>
>>> 
>>>
>>> 49  chkDup ns =
>>>
>>>  ^^^^^^^^^^^...
>>>
>>>
>>>
>>>
>>>
>>> So is there a nicer and working way, how to change my simple example? Is
>>> there a way, how to make it compile? Or is it useless to do that, original
>>> function is just fine...
>>>
>>>
>>>
>>> Best regards,
>>>
>>> Dušan
>>>
>>>
>>> _______________________________________________
>>> HaskellCafe mailing list
>>> To (un)subscribe, modify options or view archives go to:
>>> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
>>> Only members subscribed via the mailman list are allowed to post.
>>
>>
>>
>> 
>>
>> Paolo Veronelli (paolo.veronelli at gmail.com)
>>
>>
>> *Functional developer @ global.de *
>>
>>
>
> 
>
> Paolo Veronelli (paolo.veronelli at gmail.com)
>
>
> *Functional developer @ global.de *
>
>

Paolo Veronelli (paolo.veronelli at gmail.com)
*Functional developer @ global.de *
 next part 
An HTML attachment was scrubbed...
URL:
From kolar at fit.vut.cz Wed Aug 7 12:38:12 2019
From: kolar at fit.vut.cz (=?utf8?B?RHXFoWFuIEtvbMOhxZk=?=)
Date: Wed, 07 Aug 2019 14:38:12 +0200
Subject: [Haskellcafe] Ambiguous types
InReplyTo: <20190807122127.14952dhisipgjr6s@www.staffmail.ed.ac.uk>
References: <2162795.o9Qe6PU3hX@pckolar>
<20190807121727.18661n6493o30sis@www.staffmail.ed.ac.uk>
<20190807122127.14952dhisipgjr6s@www.staffmail.ed.ac.uk>
MessageID: <21769040.ac4hKd0Jlg@pckolar>
Thanks all for the answers, and no, they are not what I was asking for...
Not providing type signatures, yes, no type signatures provided, GHC should derive
them on its own. My question was, why it is not able to do that and how force GHC
to do that. Without extra type info...
The original type signature was simple: chkDup :: (Eq a, Num a) => [a] > Bool
I would be quite happy to have something similar, just for [] to have some generic
type  automagically :)
And no, my intention was not to make it a bit faster for larger inputs, just make
clear and clean code without extra type signatures, easy to read and simple to
understand. Reallife input has 36 six members at most.
And no, I don't want the general code to be specific for lists, thus no extra type
signatures or changes to make it more list of Ints.
So thank you once again, unfortunately, my conclusion is that writing generic code
is not always beneficial  neither for reading nor for generality...
Thank you once again,
Dušan
On středa 7. srpna 2019 13:21:27 CEST Juan Casanova wrote:
> PS: I didn't even spend much time thinking how I would probably
> implement chkDup differently even for the generic case that you want
> to do. As in, intuition tells me you don't really need an applicative
> monoid internally to do what you're trying to do. But, as I said,
> haven't thought it thoroughly, and with the code I gave you, you get
> what you were trying to do and it's not "wrong". Maybe just overkill.
>
> Quoting Juan Casanova on Wed, 07 Aug 2019
>
> 12:17:27 +0100:
> > To build up on Paolino's answer, and maybe, if you're like me, give
> > you a better intuition as to why your code was incorrect, but
> > leading to essentially the same answer he gave.
> >
> > First, you didn't provide us with the type signatures for chkDup and
> > f, but I worked with the following ones to start with:
> >
> > chkDup :: forall a (t :: * > *) (f :: * > *). (Eq a, Num a,
> > Foldable t, Foldable f, Applicative f, Monoid (f a)) => t a > Bool
> >
> > f :: (Num a, Foldable t, Semigroup (t a), Applicative t, Eq a) => a
> > > (Bool, t a) > (Bool, t a)
> >
> > This gives me the same error you get even if I define chkDup _ =
> > undefined.
> >
> > The problem is that you are providing class constraints for the type
> > f, which does not appear at all in the signature of the function (t
> > a > Bool), and this makes the typechecker get super confused. Now,
> > I know why you thought this was necessary: precisely because of what
> > Paolino pointed out: mempty has an undefined type, and you tried to
> > fix this by saying "This mempty is of type f, which I don't care for
> > the type, just that it is a Semigroup and Applicative". But this is
> > a mistake. So, if you just remove the f altogether from the class
> > constraints of the chkDup type signature, and leave it like this:
> >
> > chkDup :: forall a (t :: * > *) (f :: * > *). (Eq a, Num a,
> > Foldable t) => t a > Bool
> >
> > You still get an error, but now you get the actual error message
> > that you're looking for: "Could not deduce Foldable t0 arising from
> > a use of f".
> >
> > The right way to fix this is how Paolino said: Specify what Foldable
> > you're going to use (recommended: list) (so, use [] instead of
> > mempty). The point is, since the type f is not part of the input NOR
> > the output of the function chkDup, and instead it is just an
> > internal tool that you use to compute chkDup, there's no reason to
> > want to be generic about it, there's no advantage in that. The
> > advantage in genericity using typeclasses is: 1. If it's in the
> > input, you allow the user of the function to provide you with any
> > type that fulfills the class. 2. You make it very clear that
> > everything you do with that parameter is related to its typeclass
> > instance, as there is no way to inspect the actual type. 3. If it's
> > in the output, you don't let users of the function make any
> > assumption of what that type might look like, other than its
> > typeclass instance.
> >
> > But in an internal tool that doesn't come from outside and isn't
> > output by your function, there's no reason to be generic, just use
> > lists. The only reason I could see being argued for wanting to be
> > generic would be if you'd like the user to provide you with hints as
 next part 
An HTML attachment was scrubbed...
URL:
From juan.casanova at ed.ac.uk Wed Aug 7 12:53:17 2019
From: juan.casanova at ed.ac.uk (Juan Casanova)
Date: Wed, 07 Aug 2019 13:53:17 +0100
Subject: [Haskellcafe] Ambiguous types
InReplyTo: <21769040.ac4hKd0Jlg@pckolar>
References: <2162795.o9Qe6PU3hX@pckolar>
<20190807121727.18661n6493o30sis@www.staffmail.ed.ac.uk>
<20190807122127.14952dhisipgjr6s@www.staffmail.ed.ac.uk>
<21769040.ac4hKd0Jlg@pckolar>
MessageID: <20190807135317.785373zpisqog4g0@www.staffmail.ed.ac.uk>
There are two important things to say about your email, but one is a
lot more important than the other.
> And no, I don't want the general code to be specific for lists, thus
> no extra type
> signatures or changes to make it more list of Ints.
You did not understand my (and Paolino's) point about using lists. By
using lists *internally* you're not making it less generic. The
function still works for any foldable. But you are building another
foldable *within your function* as a way to check for duplication,
that isn't returned. When you build an element, you need to specify
it's type (or use a function passed as parameter to build it). In this
case, list is just as good as any other foldable for the internal
workings. You can use another foldable if you wish, but you need to
use some foldable, because Foldable itself is only a behavioural
definition that cannot be used directly. Thus, what I personally said
about efficiency was in the case that you wanted the user to be able
to *specify as an argument* what instance of Foldable to use for this.
If you don't care about efficiency, then use lists, or any other
foldable of your choice.
Let me see if I can make this clearer with an analogy. You go to a
workshop and ask them to build a metal bar for you. You say: it needs
to be this size, this weight and be able to resist this amount of
strength (that would be equivalent to the typeclass, it needs to be
Foldable). Now, what would break the transparency that typeclasses and
genericity provide would be if they asked you: "what are you going to
use this metal bar for?". They don't need to know, as long as they
produce a metal bar that fulfills your requirements. So far so good.
But now, imagine that you asked them: "I want you to build the metal
bar in such a way that it is independent of the tools that you have
available". They would be puzzled. Why do you care what tools they use
to build the metal bar? You want a metal bar with a set of
characteristics, you will get it. How they build the metal bar and how
specific that building of the metal bar may be is absolutely
irrelevant to you. This is the list. The list (or any other foldable
that you wish to use), is just the tool that you use to check for
duplicity. It is *not* the output result of your function. So using it
does not break genericity in any way.
The second, slightly less important point, is about the type
signatures. You want GHC to derive the signatures on its own? Fine.
Take the code that I provided you, and remove the type signatures. It
compiles, it works, and it infers exactly the same type signatures
that I provided. There are two reasons for which I think your approach
that "it is better if I don't specify the type signatures" is mistaken.
First, the reason you want to provide type signatures is because it
makes the code clearer. Saying that "GHC should derive the type
signatures" is a bit like writing a monofunction program and saying
"the compiler should not care about how long my functions are". Type
signatures help the programmer understand what the functions do, help
you program by making it easier to see if you can use a function or
not by looking at its type signature, and make it easier to debug by
modularizing the problems.
Second, depending on what extensions you use (and you are using
RankNTypes and KindSignatures, which are not trivial extensions), type
signatures on functions or type annotations might not be avoidable,
precisely because of ambiguity. In this particular case, they can be
removed, as I said, but there are some programs that are inevitably
ambiguous unless you explicitly specify the types. And this is not a
GHC limitation, it is a mathematical limitation of the programming
model, so type signatures are not optional sometimes.
But, as I said, if you really disagree and prefer not to provide type
signatures, then don't. The code I provided still works perfectly, and
the reason why using lists internally does not break genericity still
holds regardless of that.
Juan.
Quoting Dušan Kolář on Wed, 07 Aug 2019 14:38:12 +0200:
> Thanks all for the answers, and no, they are not what I was asking for...
>
> Not providing type signatures, yes, no type signatures provided, GHC
> should derive
> them on its own. My question was, why it is not able to do that and
> how force GHC
> to do that. Without extra type info...
>
> The original type signature was simple: chkDup :: (Eq a, Num a) =>
> [a] > Bool
> I would be quite happy to have something similar, just for [] to
> have some generic
> type  automagically :)
>
> And no, my intention was not to make it a bit faster for larger
> inputs, just make
> clear and clean code without extra type signatures, easy to read and
> simple to
> understand. Reallife input has 36 six members at most.
>
>
> So thank you once again, unfortunately, my conclusion is that
> writing generic code
> is not always beneficial  neither for reading nor for generality...
>
> Thank you once again,
>
> Dušan
>
>

The University of Edinburgh is a charitable body, registered in
Scotland, with registration number SC005336.
From jaro.reinders at gmail.com Wed Aug 7 12:59:43 2019
From: jaro.reinders at gmail.com (Jaro Reinders)
Date: Wed, 7 Aug 2019 14:59:43 +0200
Subject: [Haskellcafe] Ambiguous types
InReplyTo: <21769040.ac4hKd0Jlg@pckolar>
References: <2162795.o9Qe6PU3hX@pckolar>
<20190807121727.18661n6493o30sis@www.staffmail.ed.ac.uk>
<20190807122127.14952dhisipgjr6s@www.staffmail.ed.ac.uk>
<21769040.ac4hKd0Jlg@pckolar>
MessageID: <2e43bcf146ccb830c565cce65ba8a522@gmail.com>
Another issue with not providing a type signature on internal types is
that the code can literally change meaning. In this case we can change
the meaning of your code by simply adding a type signature:
chkDup ns = fst $ foldr f (False,mempty :: (Semigroup a, Num a, Eq a) =>
Maybe a) ns
where
f _ res@(True,_) = res
f v res@(_,vs) = if v==0 then (False, vs) else (elem v vs, pure v <> vs)
Now the code doesn't do what you want anymore. How should GHC be able to
infer the types if an expression can have two different types that have
different meanings?
On 07082019 14:38, Dušan Kolář wrote:
> Thanks all for the answers, and no, they are not what I was asking for...
>
> Not providing type signatures, yes, no type signatures provided, GHC should derive
> them on its own. My question was, why it is not able to do that and how force GHC
> to do that. Without extra type info...
>
> The original type signature was simple: chkDup :: (Eq a, Num a) => [a] > Bool
> I would be quite happy to have something similar, just for [] to have some generic
> type  automagically :)
>
> And no, my intention was not to make it a bit faster for larger inputs, just make
> clear and clean code without extra type signatures, easy to read and simple to
> understand. Reallife input has 36 six members at most.
>
> And no, I don't want the general code to be specific for lists, thus no extra type
> signatures or changes to make it more list of Ints.
>
> So thank you once again, unfortunately, my conclusion is that writing generic code
> is not always beneficial  neither for reading nor for generality...
>
> Thank you once again,
>
> Dušan
>
>
> On středa 7. srpna 2019 13:21:27 CEST Juan Casanova wrote:
>> PS: I didn't even spend much time thinking how I would probably
>> implement chkDup differently even for the generic case that you want
>> to do. As in, intuition tells me you don't really need an applicative
>> monoid internally to do what you're trying to do. But, as I said,
>> haven't thought it thoroughly, and with the code I gave you, you get
>> what you were trying to do and it's not "wrong". Maybe just overkill.
>>
>> Quoting Juan Casanova on Wed, 07 Aug 2019
>>
>> 12:17:27 +0100:
>>> To build up on Paolino's answer, and maybe, if you're like me, give
>>> you a better intuition as to why your code was incorrect, but
>>> leading to essentially the same answer he gave.
>>>
>>> First, you didn't provide us with the type signatures for chkDup and
>>> f, but I worked with the following ones to start with:
>>>
>>> chkDup :: forall a (t :: * > *) (f :: * > *). (Eq a, Num a,
>>> Foldable t, Foldable f, Applicative f, Monoid (f a)) => t a > Bool
>>>
>>> f :: (Num a, Foldable t, Semigroup (t a), Applicative t, Eq a) => a
>>> > (Bool, t a) > (Bool, t a)
>>>
>>> This gives me the same error you get even if I define chkDup _ =
>>> undefined.
>>>
>>> The problem is that you are providing class constraints for the type
>>> f, which does not appear at all in the signature of the function (t
>>> a > Bool), and this makes the typechecker get super confused. Now,
>>> I know why you thought this was necessary: precisely because of what
>>> Paolino pointed out: mempty has an undefined type, and you tried to
>>> fix this by saying "This mempty is of type f, which I don't care for
>>> the type, just that it is a Semigroup and Applicative". But this is
>>> a mistake. So, if you just remove the f altogether from the class
>>> constraints of the chkDup type signature, and leave it like this:
>>>
>>> chkDup :: forall a (t :: * > *) (f :: * > *). (Eq a, Num a,
>>> Foldable t) => t a > Bool
>>>
>>> You still get an error, but now you get the actual error message
>>> that you're looking for: "Could not deduce Foldable t0 arising from
>>> a use of f".
>>>
>>> The right way to fix this is how Paolino said: Specify what Foldable
>>> you're going to use (recommended: list) (so, use [] instead of
>>> mempty). The point is, since the type f is not part of the input NOR
>>> the output of the function chkDup, and instead it is just an
>>> internal tool that you use to compute chkDup, there's no reason to
>>> want to be generic about it, there's no advantage in that. The
>>> advantage in genericity using typeclasses is: 1. If it's in the
>>> input, you allow the user of the function to provide you with any
>>> type that fulfills the class. 2. You make it very clear that
>>> everything you do with that parameter is related to its typeclass
>>> instance, as there is no way to inspect the actual type. 3. If it's
>>> in the output, you don't let users of the function make any
>>> assumption of what that type might look like, other than its
>>> typeclass instance.
>>>
>>> But in an internal tool that doesn't come from outside and isn't
>>> output by your function, there's no reason to be generic, just use
>>> lists. The only reason I could see being argued for wanting to be
>>> generic would be if you'd like the user to provide you with hints as
>>>
>>> _______________________________________________
>>> HaskellCafe mailing list
>>> To (un)subscribe, modify options or view archives go to:
>>> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
>>> Only members subscribed via the mailman list are allowed to post.
From juan.casanova at ed.ac.uk Wed Aug 7 13:22:25 2019
From: juan.casanova at ed.ac.uk (Juan Casanova)
Date: Wed, 07 Aug 2019 14:22:25 +0100
Subject: [Haskellcafe] Ambiguous types
InReplyTo: <2e43bcf146ccb830c565cce65ba8a522@gmail.com>
References: <2162795.o9Qe6PU3hX@pckolar>
<20190807121727.18661n6493o30sis@www.staffmail.ed.ac.uk>
<20190807122127.14952dhisipgjr6s@www.staffmail.ed.ac.uk>
<21769040.ac4hKd0Jlg@pckolar>
<2e43bcf146ccb830c565cce65ba8a522@gmail.com>
MessageID: <20190807142225.11373snkepghqc2s@www.staffmail.ed.ac.uk>
To add and tie this in with the list choice, I must say I said
something not entirely correct: Not any foldable that you may want to
use is valid. As Jaro showed here, Maybe is a Foldable that would not
do what you want.
Now, I have no proof of the following, but I'd bet money that I'm not
wrong that: List is special as a foldable because it is general. In
other words, the function:
tolist :: Foldable t => t a > [a]
tolist = foldr (:) []
is such that for any x :: t a where Foldable t, it is true that
foldr f v x = foldr f v (tolist x)
which is to say, any structure a foldable may have is preserved when
transforming into list shape, as a foldable.
This is not an argument for saying "let's use lists all the time
instead of foldables". Of course not. But, *internally*, you can use
lists so that the program can run (because it needs an instance),
while knowing that you will not be losing any structure while using
lists, so that the overall function will work for any foldable.
I think I'll stop my ramblings now, I don't want to overload the list.
Quoting Jaro Reinders on Wed, 7 Aug 2019
14:59:43 +0200:
> Another issue with not providing a type signature on internal types is
> that the code can literally change meaning. In this case we can change
> the meaning of your code by simply adding a type signature:
>
> chkDup ns = fst $ foldr f (False,mempty :: (Semigroup a, Num a, Eq a) =>
> Maybe a) ns
> where
> f _ res@(True,_) = res
> f v res@(_,vs) = if v==0 then (False, vs) else (elem v vs, pure v <> vs)
>
> Now the code doesn't do what you want anymore. How should GHC be able to
> infer the types if an expression can have two different types that have
> different meanings?
>
> On 07082019 14:38, Dušan Kolář wrote:
>> Thanks all for the answers, and no, they are not what I was asking for...
>>
>> Not providing type signatures, yes, no type signatures provided,
>> GHC should derive
>> them on its own. My question was, why it is not able to do that and
>> how force GHC
>> to do that. Without extra type info...
>>
>> The original type signature was simple: chkDup :: (Eq a, Num a) =>
>> [a] > Bool
>> I would be quite happy to have something similar, just for [] to
>> have some generic
>> type  automagically :)
>>
>> And no, my intention was not to make it a bit faster for larger
>> inputs, just make
>> clear and clean code without extra type signatures, easy to read
>> and simple to
>> understand. Reallife input has 36 six members at most.
>>
>> And no, I don't want the general code to be specific for lists,
>> thus no extra type
>> signatures or changes to make it more list of Ints.
>>
>> So thank you once again, unfortunately, my conclusion is that
>> writing generic code
>> is not always beneficial  neither for reading nor for generality...
>>
>> Thank you once again,
>>
>> Dušan
>>
>>
>> On středa 7. srpna 2019 13:21:27 CEST Juan Casanova wrote:
>>> PS: I didn't even spend much time thinking how I would probably
>>> implement chkDup differently even for the generic case that you want
>>> to do. As in, intuition tells me you don't really need an applicative
>>> monoid internally to do what you're trying to do. But, as I said,
>>> haven't thought it thoroughly, and with the code I gave you, you get
>>> what you were trying to do and it's not "wrong". Maybe just overkill.
>>>
>>> Quoting Juan Casanova on Wed, 07 Aug 2019
>>>
>>> 12:17:27 +0100:
>>>> To build up on Paolino's answer, and maybe, if you're like me, give
>>>> you a better intuition as to why your code was incorrect, but
>>>> leading to essentially the same answer he gave.
>>>>
>>>> First, you didn't provide us with the type signatures for chkDup and
>>>> f, but I worked with the following ones to start with:
>>>>
>>>> chkDup :: forall a (t :: * > *) (f :: * > *). (Eq a, Num a,
>>>> Foldable t, Foldable f, Applicative f, Monoid (f a)) => t a > Bool
>>>>
>>>> f :: (Num a, Foldable t, Semigroup (t a), Applicative t, Eq a) => a
>>>> > (Bool, t a) > (Bool, t a)
>>>>
>>>> This gives me the same error you get even if I define chkDup _ =
>>>> undefined.
>>>>
>>>> The problem is that you are providing class constraints for the type
>>>> f, which does not appear at all in the signature of the function (t
>>>> a > Bool), and this makes the typechecker get super confused. Now,
>>>> I know why you thought this was necessary: precisely because of what
>>>> Paolino pointed out: mempty has an undefined type, and you tried to
>>>> fix this by saying "This mempty is of type f, which I don't care for
>>>> the type, just that it is a Semigroup and Applicative". But this is
>>>> a mistake. So, if you just remove the f altogether from the class
>>>> constraints of the chkDup type signature, and leave it like this:
>>>>
>>>> chkDup :: forall a (t :: * > *) (f :: * > *). (Eq a, Num a,
>>>> Foldable t) => t a > Bool
>>>>
>>>> You still get an error, but now you get the actual error message
>>>> that you're looking for: "Could not deduce Foldable t0 arising from
>>>> a use of f".
>>>>
>>>> The right way to fix this is how Paolino said: Specify what Foldable
>>>> you're going to use (recommended: list) (so, use [] instead of
>>>> mempty). The point is, since the type f is not part of the input NOR
>>>> the output of the function chkDup, and instead it is just an
>>>> internal tool that you use to compute chkDup, there's no reason to
>>>> want to be generic about it, there's no advantage in that. The
>>>> advantage in genericity using typeclasses is: 1. If it's in the
>>>> input, you allow the user of the function to provide you with any
>>>> type that fulfills the class. 2. You make it very clear that
>>>> everything you do with that parameter is related to its typeclass
>>>> instance, as there is no way to inspect the actual type. 3. If it's
>>>> in the output, you don't let users of the function make any
>>>> assumption of what that type might look like, other than its
>>>> typeclass instance.
>>>>
>>>> But in an internal tool that doesn't come from outside and isn't
>>>> output by your function, there's no reason to be generic, just use
>>>> lists. The only reason I could see being argued for wanting to be
>>>> generic would be if you'd like the user to provide you with hints as
>>>>
>>>> _______________________________________________
>>>> HaskellCafe mailing list
>>>> To (un)subscribe, modify options or view archives go to:
>>>> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
>>>> Only members subscribed via the mailman list are allowed to post.
> _______________________________________________
> HaskellCafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
> Only members subscribed via the mailman list are allowed to post.

The University of Edinburgh is a charitable body, registered in
Scotland, with registration number SC005336.
From byorgey at gmail.com Wed Aug 7 13:36:42 2019
From: byorgey at gmail.com (Brent Yorgey)
Date: Wed, 7 Aug 2019 08:36:42 0500
Subject: [Haskellcafe] Ambiguous types
InReplyTo: <20190807142225.11373snkepghqc2s@www.staffmail.ed.ac.uk>
References: <2162795.o9Qe6PU3hX@pckolar>
<20190807121727.18661n6493o30sis@www.staffmail.ed.ac.uk>
<20190807122127.14952dhisipgjr6s@www.staffmail.ed.ac.uk>
<21769040.ac4hKd0Jlg@pckolar>
<2e43bcf146ccb830c565cce65ba8a522@gmail.com>
<20190807142225.11373snkepghqc2s@www.staffmail.ed.ac.uk>
MessageID:
On Wed, Aug 7, 2019, 8:22 AM Juan Casanova wrote:
> List is special as a foldable because it is general. In
> other words, the function:
>
> tolist :: Foldable t => t a > [a]
> tolist = foldr (:) []
>
> is such that for any x :: t a where Foldable t, it is true that
>
> foldr f v x = foldr f v (tolist x)
>
> which is to say, any structure a foldable may have is preserved when
> transforming into list shape, as a foldable.
>
This is true. In fact "Listable" might have been a better name than
Foldable. (In particular Foldable has nothing to do with generic folds aka
catamorphisms.)
Brent
>
 next part 
An HTML attachment was scrubbed...
URL:
From ietfdane at dukhovni.org Wed Aug 7 22:49:54 2019
From: ietfdane at dukhovni.org (Viktor Dukhovni)
Date: Wed, 7 Aug 2019 18:49:54 0400
Subject: [Haskellcafe] Ambiguous types
InReplyTo: <2162795.o9Qe6PU3hX@pckolar>
References: <2162795.o9Qe6PU3hX@pckolar>
MessageID: <41D9E14FEA624848BD130A7D703F8B79@dukhovni.org>
> On Aug 7, 2019, at 5:52 AM, Dušan Kolář wrote:
>
> So is there a nicer and working way, how to change my simple example? Is there a way, how to make it compile? Or is it useless to do that, original function is just fine...
The closest working version is:
checkDup ns = fst $ foldr f (False, []) ns
where
f _ res@(True, _) = res
f 0 res@(_, vs) = (False, vs)
f v res@(_, vs) = (elem v vs, v : vs)
replacing "mempty" with "[]" removes the ambiguity, which
is was a logical inevitability, and not some limitation of
GHC's type inference...

Viktor.
From adam at ahri.net Fri Aug 9 15:28:08 2019
From: adam at ahri.net (Adam)
Date: Fri, 9 Aug 2019 16:28:08 +0100
Subject: [Haskellcafe] Unifying an IO read into a TChan?
MessageID:
Hello Café!
It's my first post here so do tell me if I get something wrong :)
I'm in the process of writing an event database; it should adhere to ACID
principles and is specifically aimed at persisting then broadcasting events
in some eventdriven system.
The code is up on GitHub and I expect to build a Hackage package soon, for
now I'm prototyping with Stack generating the .cabal file, but this will
change when things settle down.
My question is about a function I have:
readEvents :: Word64 > Connection > IO ([IndexedEvent], TChan
IndexedEvent)
readEvents from conn = do
(ec, chan) < atomically $ (,)
<$> (readTVar $ evCount conn)
<*> (dupTChan $ readSubs conn)
evsFromDisk < readEventsRange from ec conn
pure (evsFromDisk, chan)
For context please see the whole file:
https://github.com/ahri/eventdb/blob/4747afb/src/Database/EventDB.hs#L172L180
1. What I'd like to understand is how I might unify the return type into a
single `TChan IndexedEvent` which would contain first the `evsFromDisk` and
then pull from the broadcast channel `chan`. The only way I can think to do
it is to fork a thread to write to a new broadcast channel  which might be
unexpected for a client of my API and seems quite heavyweight.
I have a connected couple of questions too, related to lazy IO as I'm still
learning Haskell!
2. does my `readEventsRange` function pull all events into memory or does
lazy IO magically avoid this by streaming the data through from the disk?
3. if I did fork a thread and write the `evsFromDisk` and the sit in a `
forever` reading off `chan` and onto my new broadcast channel, would this
result in all the written events being read into memory or does the
laziness spread so that only when the client does a `readTChan` will the
data flow through from the disk/`chan`?
Thanks for reading,
Adam
 next part 
An HTML attachment was scrubbed...
URL:
From komendantskaya at gmail.com Mon Aug 12 07:29:07 2019
From: komendantskaya at gmail.com (Ekaterina Komendantskaya)
Date: Mon, 12 Aug 2019 08:29:07 +0100
Subject: [Haskellcafe] PADL 2020 (coallocated with POPL 2020): first call
for papers
MessageID:
22nd International Symposium on Practical Aspects of Declarative Languages
(PADL 2020)https://popl20.sigplan.org/home/PADL2020,2021 January 2019,
New Orleans, Louisiana, United StatesColocated with ACM POPL 2020 (
https://popl20.sigplan.org/)

*Declarative programming languages* is an umbrella term for functional,
logic, answerset and constraintsolving programming paradigms, as well as
a range of verification and theorem proving methods that rely on such
languages. These languages have been successfully applied to many different
realworld situations, ranging from data base management and active
networks to software engineering and decision support systems.
New developments in theory and implementation have opened up new
application areas. At the same time, applications of declarative languages
to challenging problems raise new intriguing research questions, such as
scalable design and implementation, language extensions for application
deployment, and programming environments. Thus, applications drive the
progress in the theory and implementation of declarative systems, and
benefit from this progress as well.
PADL is a wellestablished forum for researchers and practitioners to
present original work emphasising novel applications and implementation
techniques for all forms of declarative programming, including functional
and logic programming, database and constraint programming, theorem
proving. Topics of interest include, but are not limited to:
 Innovative applications of declarative languages
 Declarative domainspecific languages and applications
 Practical applications of theoretical results
 New language developments and their impact on applications
 Declarative languages for software engineering
 Evaluation of implementation techniques on practical applications
 Practical experiences and industrial applications
 Novel uses of declarative languages in the classroom
 Practical languages and extensions such as probabilistic and reactive
languages
*PADL 2020 especially welcomes new ideas and approaches pertaining to
applications, design and implementation of declarative languages going
beyond the scope of the past PADL symposia, for example database languages
and contract languages.*
Important Dates and Submission Guidelines:
 Abstracts due: 11 October 2019
 Papers due: 18 October 2019
 Notification to authors: 18 November 2019
 Cameraready: 29 November 2020
Authors should submit an electronic copy of the full paper in PDF using the
Springer LNCS format. The submission will be done through EasyChair
conference system: https://easychair.org/conferences/?conf=padl2020
All submissions must be original work written in English. Submissions must
be unpublished and not submitted for publication elsewhere. Work that
already appeared in unpublished or informally published workshops
proceedings may be submitted but the authors should notify the program
chair about the place on which it has previously appeared.
PADL 2020 will accept both technical and application papers:
*Technical papers* must describe original, previously unpublished research
results. Technical papers must not exceed 15 pages (plus one page of
references) in Springer LNCS format.
*Application papers* are a mechanism to present important practical
applications of declarative languages that occur in industry or in areas of
research other than Computer Science. Application papers are expected to
describe complex and/or realworld applications that rely on an innovative
use of declarative languages. Application descriptions, engineering
solutions and realworld experiences (both positive and negative) are
solicited. The limit for application papers is 8 pages in Springer LNCS
format but such papers can also point to sites with supplemental
information about the application or the system that they describe.
*The proceedings of PADL 2020 will appear in the LNCS series of Springer
Verlag: https://www.springer.com/gp/computerscience/lncs
.*
*************************************************************
For further questions, please contact the conference chairs:
Ekaterina Komendantskaya
and
Annie Liu
 next part 
An HTML attachment was scrubbed...
URL:
From S.J.Thompson at kent.ac.uk Mon Aug 12 12:33:55 2019
From: S.J.Thompson at kent.ac.uk (Simon Thompson)
Date: Mon, 12 Aug 2019 13:33:55 +0100
Subject: [Haskellcafe] Research Associate at Kent in Trustworthy Refactoring
MessageID: <5B9C56E634C24553845C141275DAB55A@kent.ac.uk>
We are seeking to recruit an enthusiastic Research Associate to join the final year of the EPSRC project “Trustworthy Refactoring”. The overall goal of this project is to investigate the design and construction of trustworthy refactoring tools: this means that when refactorings are performed, the tools will provide strong evidence that the refactoring has not changed the behaviour of the code, built on a solid theoretical understanding of the semantics of the language, thus establishing a step change in the practice of refactoring.
If you have have a PhD in Computer Science, awarded or nearing completion, experience in functional programming (e.g. Haskell/ML/Erlang/…) and experience of using a proof assistant (e.g. Coq/Isabelle/HOL/…), you have what we’re looking for.
More details about the project are here:
https://jobs.kent.ac.uk/vacancy.aspx?ref=STM04719
If you have any questions about the post do contact one of us by email: Scott Owens (s.a.owens at kent.ac.uk) and Simon Thompson (s.j.thompson at kent.ac.uk) : we look forward to hearing from you.
Scott and Simon
Simon Thompson  Professor of Logic and Computation
School of Computing  University of Kent  Canterbury, CT2 7NF, UK
s.j.thompson at kent.ac.uk  M +44 7986 085754  W www.cs.kent.ac.uk/~sjt
From P.Achten at cs.ru.nl Thu Aug 15 11:23:26 2019
From: P.Achten at cs.ru.nl (Peter Achten)
Date: Thu, 15 Aug 2019 13:23:26 +0200
Subject: [Haskellcafe] [TFP'20] first call for papers: Trends in Functional
Programming 2020, 1314 February, Krakow, Poland
MessageID:

First call for papers
21st Symposium on Trends in Functional Programming
tfp2020.org

The symposium on Trends in Functional Programming (TFP) is an international
forum for researchers with interests in all aspects of functional
programming,
taking a broad view of current and future trends in the area. It aspires
to be
a lively environment for presenting the latest research results, and other
contributions.
* TFP is moving to new winter dates, to provide an FP forum in between the
annual ICFP events.
* TFP offers a supportive reviewing process designed to help less
experienced
authors succeed, with two rounds of review, both before and after the
symposium itself. Authors have an opportunity to address reviewers'
concerns
before final decisions on publication in the proceedings.
* TFP offers two "best paper" awards, the John McCarthy award for best
paper,
and the David Turner award for best student paper.
* This year we are particularly excited to colocate with Lambda Days in
beautiful Krakow. Lambda Days is a vibrant developer conference with
hundreds
of attendees and a lively programme of talks on functional
programming in
practice. TFP will be held in the same venue, and participants will
be able
to sessionhop between the two events.
Important Dates

Submission deadline for presymposium review: 15th November, 2019
Submission deadline for draft papers: 10th January, 2020
Symposium dates: 1314th February, 2020
Visit tfp2020.org for more information.
From n.wu at imperial.ac.uk Fri Aug 16 08:27:42 2019
From: n.wu at imperial.ac.uk (Wu, Nicolas G)
Date: Fri, 16 Aug 2019 08:27:42 +0000
Subject: [Haskellcafe] PhD position at Imperial College London
MessageID:
# PhD Position in Functional Programming: Effect Handlers at Imperial College London
Applications are invited for a PhD student in Functional Programming under the supervision of Dr Nicolas Wu at Imperial College London.
The project aims to enhance the applications of effects and handlers by developing scoped contextual operations and effects. There are two main interrelated topics:
1. Developing the foundations of operations and effects that are confined within a scope and that are sensitive to context, thus widening the applications of effect handlers.
2. Producing efficient implementations and demonstrating applications that allow programmers to combine and use such effects.
Addressing these topics will deliver both theoretical insight to the academic community and practical benefits to software engineers.
To apply for this position, you will need to have a strong background in at least one of the following areas: functional programming, programming language design, compilers, algebraic effects. A working understanding of Haskell is essential.
Applicants are expected to have a First Class or Distinction Masters level degree, or equivalent, in a relevant scientific or technical discipline, such as computer science or mathematics. Applicants must be fluent in spoken and written English.
The position is fully funded, covering tuition fees, travel funds and a stipend/bursary. The position is available to home, EU and overseas students.
Studentship: Untaxed bursary of £17,009 per annum (2018/19 figure including London weighting plus home/EU fees)
For more details on how to apply, please see the advertisement here:
http://www.imperial.ac.uk/computing/prospectivestudents/courses/phd/scholarships/#
listed under "PhD Position in Functional Programming: Effect Handlers". Early applications are strongly encouraged. Please be in touch with informal inquiries about the position with Dr Nicolas Wu (n.wu at imperial.ac.uk).
From rudy at matela.com.br Sun Aug 18 15:36:52 2019
From: rudy at matela.com.br (Rudy Matela)
Date: Sun, 18 Aug 2019 12:36:52 0300
Subject: [Haskellcafe] [ANN] express0.1.2: manipulate dynamically typed
Haskell expressions
MessageID: <20190818153652.j5arsaupf77a4fup@zero.localdomain>
Hello HaskellCafé,
I am happy to announce the [Express] library for Haskell.
https://github.com/rudymatela/express
Express allows manipulation of dynamically typed Haskell expressions. It
is similar to Data.Dynamic but with support for encoding applications and
variables. It provides an Expr type and over a hundred functions for
building, evaluating, comparing, folding, canonicalizing and matching
Exprs. [Express' Haddock documentation] is pretty comprehensive.
The project [README] has a few examples showing how to use Express to:
* create heterogeneous lists;
* list valid applications between expressions;
* generalize counterexamples;
* automatically generate test properties.
This library has its origins as an internal module of [Speculate] and
[Extrapolate], I am now releasing it separetely hoping that it could be
used for other purposes.
To install it, just:
$ cabal update
$ cabal install express
Then you're ready to use it:
$ ghci
> import Data.Express
> let true = val True
> :t true
true :: Expr
> print true
True :: Bool
> eval False true
True

Rudy
[Express]: https://github.com/rudymatela/express
[Express' Haddock documentation]: https://hackage.haskell.org/package/express/docs/DataExpress.html
[README]: https://github.com/rudymatela/express#readme
[Speculate]: https://github.com/rudymatela/speculate
[Extrapolate]: https://github.com/rudymatela/extrapolate
 next part 
An HTML attachment was scrubbed...
URL:
From Graham.Hutton at nottingham.ac.uk Mon Aug 19 09:52:56 2019
From: Graham.Hutton at nottingham.ac.uk (Graham Hutton)
Date: Mon, 19 Aug 2019 09:52:56 +0000
Subject: [Haskellcafe] MPC 2019  Call for Participation
MessageID: <4120D52D42BA470B8FD1C903E91E42D1@exmail.nottingham.ac.uk>
Dear all,
Registration is now open for the Mathematics of Program Construction
(MPC) conference in Portugal. MPC 2019 will feature 15 research papers
and 4 keynotes, and is colocated with Formal Methods 2019 and many
other events. See you in Porto! https://tinyurl.com/MPCPorto
Best wishes,
Graham Hutton
Program Chair, MPC 2019
======================================================================
*** CALL FOR PARTICIPATION  MPC 2019 ***
13th International Conference on Mathematics of Program Construction
79 October 2019, Porto, Portugal
Colocated with Formal Methods 2019
https://tinyurl.com/MPCPorto
======================================================================
PROGRAM: https://tinyurl.com/yxvvc5vb
ACCEPTED PAPERS: https://tinyurl.com/yyuhy8ze
REGISTRATION AND TRAVEL: https://tinyurl.com/y4uetlsr
KEYNOTE SPEAKERS:
Assia Mahboubi (MPC) INRIA, France
Annabelle McIver (MPC) Macquarie University, Australia
Tony Hoare (UTP) Oxford University, UK
Shriram Krishnamurthi (FM) Brown University, USA
BACKGROUND:
The International Conference on Mathematics of Program Construction
(MPC) aims to promote the development of mathematical principles and
techniques that are demonstrably practical and effective in the
process of constructing computer programs.
MPC 2019 will be held in Porto, Portugal from 79 October 2019, and is
colocated with the International Symposium on Formal Methods, FM 2019.
Previous conferences were held in Königswinter, Germany (2015); Madrid,
Spain (2012); Québec City, Canada (2010); Marseille, France (2008);
Kuressaare, Estonia (2006); Stirling, UK (2004); Dagstuhl, Germany (2002);
Ponte de Lima, Portugal (2000); Marstrand, Sweden (1998); Kloster Irsee,
Germany (1995); Oxford, UK (1992); Twente, The Netherlands (1989).
PROGRAM COMMITTEE:
Patrick Bahr IT University of Copenhagen, Denmark
Richard Bird University of Oxford, UK
Corina Cîrstea University of Southampton, UK
Brijesh Dongol University of Surrey, UK
João F. Ferreira University of Lisbon, Portugal
Jennifer Hackett University of Nottingham, UK
William Harrison University of Missouri, USA
Ralf Hinze University of Kaiserslautern, Germany
Zhenjiang Hu National Institute of Informatics, Japan
Graham Hutton (chair) University of Nottingham, UK
Cezar Ionescu University of Oxford, UK
Mauro Jaskelioff National University of Rosario, Argentina
Ranjit Jhala University of California, USA
Gabriele Keller Utrecht University, The Netherlands
Ekaterina Komendantskaya HeriotWatt University, UK
Chris Martens North Carolina State University, USA
Bernhard Möller University of Augsburg, Germany
ShinCheng Mu Academia Sinica, Taiwan
Mary Sheeran Chalmers University of Technology, Sweden
Alexandra Silva University College London, UK
Georg Struth University of Sheffield, UK
For any queries about the program please contact the program chair,
Graham Hutton .
CONFERENCE VENUE:
The conference will be held at the Alfândega Porto Congress Centre,
a 150 year old former custom's house located in the historic centre of
Porto on the bank of the river Douro. The venue was renovated by a
Pritzer prize winning architect and has received many awards.
LOCAL ORGANISER:
José Nuno Oliveira University of Minho, Portugal
For any queries about local issues please contact the local organiser,
José Nuno Oliveira .
======================================================================
This message and any attachment are intended solely for the addressee
and may contain confidential information. If you have received this
message in error, please contact the sender and delete the email and
attachment.
Any views or opinions expressed by the author of this email do not
necessarily reflect the views of the University of Nottingham. Email
communications with the University of Nottingham may be monitored
where permitted by law.
From david.feuer at gmail.com Mon Aug 19 10:14:20 2019
From: david.feuer at gmail.com (David Feuer)
Date: Mon, 19 Aug 2019 17:14:20 +0700
Subject: [Haskellcafe] Unfolding alongside folding
MessageID:
Thinking about fusing indexed maps for lists led me to consider the
following function, which generalizes mapWithIndex to allow arbitrary
stateful computation
foldWithUnfold
:: (a > s > Maybe (b, s))
> [a]
> s
> [b]
foldWithUnfold f = go
where
go (a : as) s
 Just (b, s') < f a s
= b : go as s'
go _ _ = []
which we can fit into fold/build fusion like so:
foldWithUnfold f as s0 =
build $ \c n >
let
go a k s
 Just (b, s') < f a s
= b `c` k s'
 otherwise
= n
in foldr go (const n) as s0
Does a function of this general nature exist in some package already?
Also, I see that the type can be expressed
foldWithUnfoldS
:: (a > StateT s Maybe b)
> [a]
> s
> [b]
Is that a better or worse way to say it?
 next part 
An HTML attachment was scrubbed...
URL:
From francesquini at gmail.com Mon Aug 19 12:14:05 2019
From: francesquini at gmail.com (Emilio Francesquini)
Date: Mon, 19 Aug 2019 09:14:05 0300
Subject: [Haskellcafe] Optimizations for list comprehension
MessageID:
Hello Cafe,
While investigating a performance problem I stumbled upon what I eventually
reduced to the example below:
module Main where
import Data.Time.Clock
outside :: Int > Int
outside n =
sum [i + j  i < range, j < range]
where
range = [0..n1]
inside :: Int > Int
inside n =
sum [i + j  i < [0..n1], j < [0..n1]]
main :: IO ()
main = do
t0 < getCurrentTime
print $ inside 10000
t1 < getCurrentTime
print $ outside 10000
t2 <getCurrentTime
print (diffUTCTime t1 t0)
print (diffUTCTime t2 t1)
Compiling with O2, up to GHC 8.2.2, both `inside` and `outside` functions
would take the same amount of time to execute. Somewhere between GHC 8.2.2
and 8.6.4 something changed (possibly some new optimization) making
`inside` run ~4x faster on my machine. With LLVM the difference is even
bigger.
It is not that `outside` got slower, but that `inside` got much faster. I'm
curious to what optimizations might be happening to the `inside` function
that would not fire on the outside function.
Any hints?
Best regards,
Emilio
 next part 
An HTML attachment was scrubbed...
URL:
From capn.freako at gmail.com Mon Aug 19 14:02:30 2019
From: capn.freako at gmail.com (David Banas)
Date: Mon, 19 Aug 2019 07:02:30 0700
Subject: [Haskellcafe] Unfolding alongside folding
InReplyTo:
References:
MessageID: <209CFA1F1F584697A33494DE39FE71FE@gmail.com>
I’m not certain, but think you might be describing hylomorphism:
https://medium.com/@JosephJnk/hylomorphisms43a5494729b7
db
> On Aug 19, 2019, at 5:00 AM, haskellcaferequest at haskell.org wrote:
>
> Does a function of this general nature exist in some package already?
 next part 
An HTML attachment was scrubbed...
URL:
From will.yager at gmail.com Mon Aug 19 14:34:42 2019
From: will.yager at gmail.com (William Yager)
Date: Mon, 19 Aug 2019 22:34:42 +0800
Subject: [Haskellcafe] Optimizations for list comprehension
InReplyTo:
References:
MessageID:
I'm not sure which exact optimizations are responsible, but based on
ddumpsimple,
* "inside" is not allocating any lists at all. It's just a couple loops
over unboxed ints
* "outside" is actually allocating a (single) list data structure and has
an inner loop and an outer loop, both of which traverse the list
GHC seems to be too aggressive about sharing "range" in "outside". Adding a
unit argument to "range" makes both functions go fast.
On Mon, Aug 19, 2019 at 8:14 PM Emilio Francesquini
wrote:
> Hello Cafe,
>
> While investigating a performance problem I stumbled upon what I
> eventually reduced to the example below:
>
> module Main where
>
> import Data.Time.Clock
>
> outside :: Int > Int
> outside n =
> sum [i + j  i < range, j < range]
> where
> range = [0..n1]
>
> inside :: Int > Int
> inside n =
> sum [i + j  i < [0..n1], j < [0..n1]]
>
> main :: IO ()
> main = do
> t0 < getCurrentTime
> print $ inside 10000
> t1 < getCurrentTime
> print $ outside 10000
> t2 <getCurrentTime
>
> print (diffUTCTime t1 t0)
> print (diffUTCTime t2 t1)
>
> Compiling with O2, up to GHC 8.2.2, both `inside` and `outside` functions
> would take the same amount of time to execute. Somewhere between GHC 8.2.2
> and 8.6.4 something changed (possibly some new optimization) making
> `inside` run ~4x faster on my machine. With LLVM the difference is even
> bigger.
>
> It is not that `outside` got slower, but that `inside` got much faster.
> I'm curious to what optimizations might be happening to the `inside`
> function that would not fire on the outside function.
>
> Any hints?
>
> Best regards,
>
> Emilio
>
>
>
>
> _______________________________________________
> HaskellCafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
> Only members subscribed via the mailman list are allowed to post.
 next part 
An HTML attachment was scrubbed...
URL:
From meng.wang at bristol.ac.uk Mon Aug 19 16:32:19 2019
From: meng.wang at bristol.ac.uk (Meng Wang)
Date: Mon, 19 Aug 2019 16:32:19 +0000
Subject: [Haskellcafe] Permenent Faculty Position in PL at University of
Bristol
MessageID: <2F9C9046AA4842978DE9760911A32E5A@bristol.ac.uk>
Dear Haskellers,
As part of a strategic expansion, the Department of Computer Science at the University of Bristol is hiring in the area of programming languages at the Lecturer (Assistant Professor) or Senior Lecturer/Reader (Associate Professor) level:
http://www.bristol.ac.uk/jobs/find/details.html?nPostingID=51136&nPostingTargetID=156814&option=28&sort=DESC&respnr=2&ID=Q50FK026203F3VBQBV7V77V83&Resultsperpage=10&lg=UK&mask=uobext
Applications in the area of functional programming are especially encouraged.
The deadline for application is 8 September 2019.
Best wishes,
Meng Wang, PhD
Senior Lecturer (Associate Professor)
Department of Computer Science
University of Bristol
Merchant Venturers Building,
Woodland Road, Clifton BS8 1UB
+44 (0) 117 954 5145
meng.wang at bristol.ac.uk
 next part 
An HTML attachment was scrubbed...
URL:
From chrisdone at gmail.com Tue Aug 20 16:36:23 2019
From: chrisdone at gmail.com (Christopher Done)
Date: Tue, 20 Aug 2019 17:36:23 +0100
Subject: [Haskellcafe] Getting both the value and name of a variable in one
expression
MessageID:
Hi all,
Do we have already a syntax for ‘foo that also contains the typed value
like TExp?
I have e.g. an AST that I want to do more static checks on it that aren’t
as convenient to do in the type system. Here’s an example:
  Check the grammar spec to produce a grammar.checkGrammar ::
(SchemaName, [(SchemaName, Schema)]) > Q ExpcheckGrammar (toplevel,
rules) =
if M.size rulesMap /= length rules
then error "Duplicate rule names in grammar."
else lift (Grammar {grammarToplevel = toplevel, grammarRules = rulesMap})
where
rulesMap = M.fromList rules
  Grammar for Haskell.grammar :: Grammargrammar = $(checkGrammar $
runDefine $ mdo
 General expression
expression < rule "Expression" (ChoiceSchema [variable,
constructor, parentheses
,tuple, let',
application, string])
application < rule "Application" (CompositeSchema [expression,
expression])
parentheses < rule "Parentheses" (CompositeSchema
[openParenSchema, expression, closeParenSchema])
...
pure expression)
Here I do a trivial check for duplicates. After I’ve checked the
expression at compiletime, I Lift it so that it can be used at
runtime. That’s pretty good. But some types like (a > b) don’t Lift. So
an alternative would be:
grammar = $(checkGrammar_take2 thename 'thename)
In which checkGrammar_take2 would:
1. Use thename at compiletime for a check.
2. If the check passes, then return (VarE thename)
E.g.
checkGrammar_take2 value name = if valueFine value then varE name
elseerror "value isn't fine"
That’s actually quite a good solution because it avoids a lift, and I
didn’t transform the AST. It’s also more efficient than lifting.
But there’s no checked relationship between thename and ‘thename.
checkGrammar_take2 has no way of knowing that they refer to the same
thing. See?
Hence, if I could get e.g. `thename to produce both the value and a
name for the value, that would be cool. My gist doesn’t go this
far. It might look like this:
checkGrammar_take2 namedValue = if valueFine (getValue namedValue)
then getExp namedValue else error "value isn't fine"
and call it like:
mygrammar = checkGrammar_take2 `thename
So the semantics would be roughly similar to
[ thename ] :: TExp a
but you’d get
`thename :: Named a
where
data Named a = { namedThing :: a, nameOfThing :: Name }
I feel like the more DSLs I design, the more I’d like something like this
to perform my static checks.
Cheers,
Chris
 next part 
An HTML attachment was scrubbed...
URL:
From francesquini at gmail.com Tue Aug 20 19:12:51 2019
From: francesquini at gmail.com (Emilio Francesquini)
Date: Tue, 20 Aug 2019 16:12:51 0300
Subject: [Haskellcafe] Optimizations for list comprehension
InReplyTo:
References:
MessageID:
Thanks William!
For me it's quite unexpected to see a unit argument making that kind of
difference for the optimizer...
Anyway, one new trick added to the bag...
Tks.
On Mon, Aug 19, 2019 at 11:34 AM William Yager wrote:
> I'm not sure which exact optimizations are responsible, but based on
> ddumpsimple,
>
> * "inside" is not allocating any lists at all. It's just a couple loops
> over unboxed ints
> * "outside" is actually allocating a (single) list data structure and has
> an inner loop and an outer loop, both of which traverse the list
>
> GHC seems to be too aggressive about sharing "range" in "outside". Adding
> a unit argument to "range" makes both functions go fast.
>
> On Mon, Aug 19, 2019 at 8:14 PM Emilio Francesquini <
> francesquini at gmail.com> wrote:
>
>> Hello Cafe,
>>
>> While investigating a performance problem I stumbled upon what I
>> eventually reduced to the example below:
>>
>> module Main where
>>
>> import Data.Time.Clock
>>
>> outside :: Int > Int
>> outside n =
>> sum [i + j  i < range, j < range]
>> where
>> range = [0..n1]
>>
>> inside :: Int > Int
>> inside n =
>> sum [i + j  i < [0..n1], j < [0..n1]]
>>
>> main :: IO ()
>> main = do
>> t0 < getCurrentTime
>> print $ inside 10000
>> t1 < getCurrentTime
>> print $ outside 10000
>> t2 <getCurrentTime
>>
>> print (diffUTCTime t1 t0)
>> print (diffUTCTime t2 t1)
>>
>> Compiling with O2, up to GHC 8.2.2, both `inside` and `outside`
>> functions would take the same amount of time to execute. Somewhere between
>> GHC 8.2.2 and 8.6.4 something changed (possibly some new optimization)
>> making `inside` run ~4x faster on my machine. With LLVM the difference is
>> even bigger.
>>
>> It is not that `outside` got slower, but that `inside` got much faster.
>> I'm curious to what optimizations might be happening to the `inside`
>> function that would not fire on the outside function.
>>
>> Any hints?
>>
>> Best regards,
>>
>> Emilio
>>
>>
>>
>>
>> _______________________________________________
>> HaskellCafe mailing list
>> To (un)subscribe, modify options or view archives go to:
>> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
>> Only members subscribed via the mailman list are allowed to post.
>
>
 next part 
An HTML attachment was scrubbed...
URL:
From sylvain at haskus.fr Wed Aug 21 13:09:15 2019
From: sylvain at haskus.fr (Sylvain Henry)
Date: Wed, 21 Aug 2019 15:09:15 +0200
Subject: [Haskellcafe] Question on inductive typefamilies
MessageID: <855bef4f071ae47ce89ca0d0b23a76e1@haskus.fr>
Hi,
Suppose I have the following type family:
type family Index (n :: Nat) (l :: [k]) = (r :: k) where
Index 0 (x ': _ ) = x
Index n (_ ': xs) = Index (n1) xs
I'm using it to define a Variant type:
data V2 (vs :: [k]) where
V2 :: forall vs (n :: Nat). KnownNat n => Proxy n > Index n vs > V2 vs
Now I want to match on the Variant retrieving either the head or the
tail (another Variant):
splitV2 :: forall v vs. V2 (v:vs) > Either v (V2 vs)
splitV2 = \case
V2 (n1 :: Proxy n) v > case sameNat n1 (Proxy @0) of
Just Refl > Left v
Nothing > Right (V2 (Proxy @(n1)) v)
It fails to typecheck with:
Couldn't match type ‘Index n (v : vs)’ with ‘Index (n  1) vs’
Expected type: Index (n  1) vs
Actual type: Index n vs1
NB: ‘Index’ is a noninjective type family
Is there a way to make this work?
This is highly speculative as I'm not very familiar with typechecking:
would it be sound to make the inductive Index family "weakly" injective?
I.e. somehow produce a typing rule for the type family:
forall n n' x xs xs'.
Solving: Index n (x ': xs) ~ Index (n'1) xs'
Is equivalent to solving: if n /= 0 then (n ~ n', xs ~ xs') else (x
~ Index (n'1) xs')
Here we could know that "n /= 0" thanks to the match on "sameNat n1
(Proxy @0)".
("weakly" because we have some form of injectivity on the shape of the
list but not on its contents)
Any pointer on this kind of stuff in research papers, Coq, Agda, etc. ?
Thanks,
Sylvain
From mail at nh2.me Wed Aug 21 13:28:01 2019
From: mail at nh2.me (=?UTF8?Q?Niklas_Hamb=c3=bcchen?=)
Date: Wed, 21 Aug 2019 15:28:01 +0200
Subject: [Haskellcafe] Optimizations for list comprehension
InReplyTo:
References:
MessageID: <57e8b6293417a4ae5a198b40195e9f0e@nh2.me>
Please file a GHC issue for this, to avoid that Haskell gets slower over time :)
On 20/08/2019 21:12, Emilio Francesquini wrote:
> For me it's quite unexpected to see a unit argument making that kind of difference for the optimizer...
>
> Anyway, one new trick added to the bag...
From claude at mathr.co.uk Wed Aug 21 13:45:49 2019
From: claude at mathr.co.uk (Claude HeilandAllen)
Date: Wed, 21 Aug 2019 14:45:49 +0100
Subject: [Haskellcafe] Optimizations for list comprehension
InReplyTo:
References:
MessageID: <1d56916ccf9d21ac68a952a152c4de7c@mathr.co.uk>
Hi,
On 20/08/2019 20:12, Emilio Francesquini wrote:
> Thanks William!
>
> For me it's quite unexpected to see a unit argument making that kind
> of difference for the optimizer...
>
> Anyway, one new trick added to the bag...
>
> Tks.
>
>
>
> On Mon, Aug 19, 2019 at 11:34 AM William Yager > wrote:
>
> I'm not sure which exact optimizations are responsible, but based
> on ddumpsimple,
>
> * "inside" is not allocating any lists at all. It's just a couple
> loops over unboxed ints
> * "outside" is actually allocating a (single) list data structure
> and has an inner loop and an outer loop, both of which traverse
> the list
>
> GHC seems to be too aggressive about sharing "range" in "outside".
> Adding a unit argument to "range" makes both functions go fast.
>
In "outside", "range" is a single (monomorphic) CAF binding, so I would
expect it to be shared aggressively.
Even if you do something like "inside" with explicit naming:
inside2 :: Int > Int
inside2 n =
sum [i + j  i < range1, j < range2]
where
range1 = [0..n1]
range2 = [0..n1]
then "range2" is shared between all iterations over "range1", which I
expect to be allocated and traversed. I haven't tested to be sure.
Historically I have used crass hacks to prevent sharing by introducing
data dependencies:
inside3 :: Int > Int
inside3 n =
sum [i + j  i < [0..n1], j < [i+0i..n1]]
That "inside" can be optimized to avoid allocations of the inner loop is
a pleasant surprise, I hope it doesn't lead to unpleasant surprises in
other circumstances.
>
> On Mon, Aug 19, 2019 at 8:14 PM Emilio Francesquini
> > wrote:
>
> Hello Cafe,
>
> While investigating a performance problem I stumbled upon what
> I eventually reduced to the example below:
>
> module Main where
>
> import Data.Time.Clock
>
> outside :: Int > Int
> outside n =
> sum [i + j  i < range, j < range]
> where
> range = [0..n1]
>
> inside :: Int > Int
> inside n =
> sum [i + j  i < [0..n1], j < [0..n1]]
>
> main :: IO ()
> main = do
> t0 < getCurrentTime
> print $ inside 10000
> t1 < getCurrentTime
> print $ outside 10000
> t2 <getCurrentTime
>
> print (diffUTCTime t1 t0)
> print (diffUTCTime t2 t1)
>
> Compiling with O2, up to GHC 8.2.2, both `inside` and
> `outside` functions would take the same amount of time to
> execute. Somewhere between GHC 8.2.2 and 8.6.4 something
> changed (possibly some new optimization) making `inside` run
> ~4x faster on my machine. With LLVM the difference is even bigger.
>
> It is not that `outside` got slower, but that `inside` got
> much faster. I'm curious to what optimizations might be
> happening to the `inside` function that would not fire on the
> outside function.
>
> Any hints?
>
Claude

https://mathr.co.uk
From lysxia at gmail.com Wed Aug 21 14:46:25 2019
From: lysxia at gmail.com (Liyao Xia)
Date: Wed, 21 Aug 2019 10:46:25 0400
Subject: [Haskellcafe] Question on inductive typefamilies
InReplyTo: <855bef4f071ae47ce89ca0d0b23a76e1@haskus.fr>
References: <855bef4f071ae47ce89ca0d0b23a76e1@haskus.fr>
MessageID: <159641df6a6a45b73618b80b3489d5f0@gmail.com>
Hi Sylvain,
The problem is that in the case where `n1` is not equal to `0`, this
unequality is not made available as a constraint solver (whereas in the
case where they are equal, the `Refl` constructor makes the
corresponding equality constraint available).
In fact, there is no builtin "unequality constraint" that acts as a
counterpart to `~` (it does not seem quite straightforward how that
would even work), but there is one way to encode it as a boolean type
family `((n == 0) ~ 'False)`. That requires changing type families to
patternmatch on `n == 0` instead of `n` directly, and possibly
additional gymnastics to reflect the comparison at termlevel:
type Index n l = IndexIf (n == 0) n l
type family IndexIf (b :: Bool) (n :: Nat) (l :: [k]) :: k where
IndexIf 'False n (x ': _ ) = x
IndexIf 'True n (_ ': xs) = Index (n  1) xs
Cheers,
Liyao
On 8/21/19 9:09 AM, Sylvain Henry wrote:
> Hi,
>
> Suppose I have the following type family:
>
> type family Index (n :: Nat) (l :: [k]) = (r :: k) where
> Index 0 (x ': _ ) = x
> Index n (_ ': xs) = Index (n1) xs
>
> I'm using it to define a Variant type:
>
> data V2 (vs :: [k]) where
> V2 :: forall vs (n :: Nat). KnownNat n => Proxy n > Index n vs >
> V2 vs
>
> Now I want to match on the Variant retrieving either the head or the
> tail (another Variant):
>
> splitV2 :: forall v vs. V2 (v:vs) > Either v (V2 vs)
> splitV2 = \case
> V2 (n1 :: Proxy n) v > case sameNat n1 (Proxy @0) of
> Just Refl > Left v
> Nothing > Right (V2 (Proxy @(n1)) v)
>
> It fails to typecheck with:
>
> Couldn't match type ‘Index n (v : vs)’ with ‘Index (n  1) vs’
> Expected type: Index (n  1) vs
> Actual type: Index n vs1
> NB: ‘Index’ is a noninjective type family
>
>
> Is there a way to make this work?
>
>
> This is highly speculative as I'm not very familiar with typechecking:
> would it be sound to make the inductive Index family "weakly" injective?
> I.e. somehow produce a typing rule for the type family:
>
> forall n n' x xs xs'.
> Solving: Index n (x ': xs) ~ Index (n'1) xs'
> Is equivalent to solving: if n /= 0 then (n ~ n', xs ~ xs') else (x
> ~ Index (n'1) xs')
>
> Here we could know that "n /= 0" thanks to the match on "sameNat n1
> (Proxy @0)".
>
> ("weakly" because we have some form of injectivity on the shape of the
> list but not on its contents)
>
> Any pointer on this kind of stuff in research papers, Coq, Agda, etc. ?
>
> Thanks,
> Sylvain
>
> _______________________________________________
> HaskellCafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
> Only members subscribed via the mailman list are allowed to post.
From simonpj at microsoft.com Wed Aug 21 15:47:58 2019
From: simonpj at microsoft.com (Simon Peyton Jones)
Date: Wed, 21 Aug 2019 15:47:58 +0000
Subject: [Haskellcafe] Optimizations for list comprehension
InReplyTo:
References:
MessageID:
I think what is happening is that
* In “inside” there are two distinct lists [0..n1], each used once; they are fused with their consumers.
* In “outside” there is one list [0..n1], which is used twice. GHC is paranoid about duplicating work (and would be right to do so if producing the list was expensive), so it does not fuse the list with its two consumers.
In this case GHC’s paranoia is not justified. It’d be better to duplicate the production of [0..n1] so that it can fuse with its consumers.
One way to address this problem might be “cheapBuild”. There’s a ticket about this: https://gitlab.haskell.org/ghc/ghc/issues/7206. I see that a year ago the TL;DR was “Conclusion: let's do it. Ensuring that a Note gives a clear explanation, and points to this ticket.” But no one yet has.
Maybe someone might see if the cheapBuild idea really does solve this particular case.
Simon
From: HaskellCafe On Behalf Of William Yager
Sent: 19 August 2019 15:35
To: Emilio Francesquini
Cc: Haskell Cafe
Subject: Re: [Haskellcafe] Optimizations for list comprehension
I'm not sure which exact optimizations are responsible, but based on ddumpsimple,
* "inside" is not allocating any lists at all. It's just a couple loops over unboxed ints
* "outside" is actually allocating a (single) list data structure and has an inner loop and an outer loop, both of which traverse the list
GHC seems to be too aggressive about sharing "range" in "outside". Adding a unit argument to "range" makes both functions go fast.
On Mon, Aug 19, 2019 at 8:14 PM Emilio Francesquini > wrote:
Hello Cafe,
While investigating a performance problem I stumbled upon what I eventually reduced to the example below:
module Main where
import Data.Time.Clock
outside :: Int > Int
outside n =
sum [i + j  i < range, j < range]
where
range = [0..n1]
inside :: Int > Int
inside n =
sum [i + j  i < [0..n1], j < [0..n1]]
main :: IO ()
main = do
t0 < getCurrentTime
print $ inside 10000
t1 < getCurrentTime
print $ outside 10000
t2 <getCurrentTime
print (diffUTCTime t1 t0)
print (diffUTCTime t2 t1)
Compiling with O2, up to GHC 8.2.2, both `inside` and `outside` functions would take the same amount of time to execute. Somewhere between GHC 8.2.2 and 8.6.4 something changed (possibly some new optimization) making `inside` run ~4x faster on my machine. With LLVM the difference is even bigger.
It is not that `outside` got slower, but that `inside` got much faster. I'm curious to what optimizations might be happening to the `inside` function that would not fire on the outside function.
Any hints?
Best regards,
Emilio
_______________________________________________
HaskellCafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
Only members subscribed via the mailman list are allowed to post.
 next part 
An HTML attachment was scrubbed...
URL:
From mgsloan at gmail.com Wed Aug 21 16:31:08 2019
From: mgsloan at gmail.com (Michael Sloan)
Date: Wed, 21 Aug 2019 10:31:08 0600
Subject: [Haskellcafe] Getting both the value and name of a variable in
one expression
InReplyTo:
References:
MessageID:
One potential solution here is to have checkGrammar_take2 return an
expression which returns an expression. I haven't tried compiling
this, but something roughly like:
checkGrammar_2 name = [ if valueFine $(varE name) then varE name else
error "value isn't fine" ]
Then it'd be used like $($(checkGrammar_2 'thename)). The thorphans
package can also be useful for this because it provides Lift instances
for the TH AST.
Michael
On Tue, Aug 20, 2019 at 10:36 AM Christopher Done wrote:
>
> Hi all,
>
> Do we have already a syntax for ‘foo that also contains the typed value like TExp?
>
> I have e.g. an AST that I want to do more static checks on it that aren’t as convenient to do in the type system. Here’s an example:
>
>   Check the grammar spec to produce a grammar.
> checkGrammar :: (SchemaName, [(SchemaName, Schema)]) > Q Exp
> checkGrammar (toplevel, rules) =
> if M.size rulesMap /= length rules
> then error "Duplicate rule names in grammar."
> else lift (Grammar {grammarToplevel = toplevel, grammarRules = rulesMap})
> where
> rulesMap = M.fromList rules
>
>   Grammar for Haskell.
> grammar :: Grammar
> grammar = $(checkGrammar $ runDefine $ mdo
>  General expression
> expression < rule "Expression" (ChoiceSchema [variable, constructor, parentheses
> ,tuple, let', application, string])
> application < rule "Application" (CompositeSchema [expression, expression])
> parentheses < rule "Parentheses" (CompositeSchema [openParenSchema, expression, closeParenSchema])
>
> ...
> pure expression)
>
> Here I do a trivial check for duplicates. After I’ve checked the
> expression at compiletime, I Lift it so that it can be used at
> runtime. That’s pretty good. But some types like (a > b) don’t Lift. So
> an alternative would be:
>
> grammar = $(checkGrammar_take2 thename 'thename)
>
> In which checkGrammar_take2 would:
>
> Use thename at compiletime for a check.
> If the check passes, then return (VarE thename)
>
> E.g.
>
> checkGrammar_take2 value name = if valueFine value then varE name else
> error "value isn't fine"
>
> That’s actually quite a good solution because it avoids a lift, and I
> didn’t transform the AST. It’s also more efficient than lifting.
>
> But there’s no checked relationship between thename and ‘thename.
> checkGrammar_take2 has no way of knowing that they refer to the same
> thing. See?
>
> Hence, if I could get e.g. `thename to produce both the value and a
> name for the value, that would be cool. My gist doesn’t go this
> far. It might look like this:
>
> checkGrammar_take2 namedValue = if valueFine (getValue namedValue) then getExp namedValue else error "value isn't fine"
>
> and call it like:
>
> mygrammar = checkGrammar_take2 `thename
>
> So the semantics would be roughly similar to
>
> [ thename ] :: TExp a
>
> but you’d get
>
> `thename :: Named a
>
> where
>
> data Named a = { namedThing :: a, nameOfThing :: Name }
>
> I feel like the more DSLs I design, the more I’d like something like this to perform my static checks.
>
> Cheers,
>
> Chris
>
> _______________________________________________
> HaskellCafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
> Only members subscribed via the mailman list are allowed to post.
From sylvain at haskus.fr Thu Aug 22 08:33:32 2019
From: sylvain at haskus.fr (Sylvain Henry)
Date: Thu, 22 Aug 2019 10:33:32 +0200
Subject: [Haskellcafe] Question on inductive typefamilies
InReplyTo: <159641df6a6a45b73618b80b3489d5f0@gmail.com>
References: <855bef4f071ae47ce89ca0d0b23a76e1@haskus.fr>
<159641df6a6a45b73618b80b3489d5f0@gmail.com>
MessageID: <5f958804f272a9daf790622e262a1069@haskus.fr>
Hi Liyao,
Thanks for your answer. Sadly I haven't managed to make it work this way
neither.
In addition I need a "KnownNat (n1)" while I only have "KnownNat n"
(and the knowledge that n > 0). For the record, it works with an
unsafeCoerce:
data V2 (vs :: [k]) where
V2 :: forall vs (n :: Nat). KnownNat n => Proxy n > Index n vs >
V2 vs
splitV2 :: forall v vs. V2 (v:vs) > Either (V2 vs) v
{# INLINE splitV2 #}
splitV2 = \case
V2 (n1 :: Proxy n) v > case sameNat n1 (Proxy @0) of
Just Refl > Right v
Nothing > case someNatVal (natVal n1  1) of
SomeNat (n2 :: Proxy n') > case unsafeCoerce Refl :: Index n
(v:vs) :~: Index n' vs of
Refl > Left (V2 n2 v)
instance Show (V2 '[]) where
{# INLINABLE show #}
show = undefined
instance (Show x, Show (V2 xs)) => Show (V2 (x ': xs)) where
{# INLINABLE show #}
show v = case splitV2 v of
Right x > show x
Left xs > show xs
test :: V2 '[Int,Word,String] > String
test v = show v
However the generated Core isn't as pretty as with the previous
representation (which uses unsafeCoerce for the value, not for the index):
data Variant (types :: [*]) = Variant {# UNPACK #} !Word Any
I'll stick to this one for now.
Sylvain
On 21/08/2019 16:46, Liyao Xia wrote:
> Hi Sylvain,
>
> The problem is that in the case where `n1` is not equal to `0`, this
> unequality is not made available as a constraint solver (whereas in
> the case where they are equal, the `Refl` constructor makes the
> corresponding equality constraint available).
>
> In fact, there is no builtin "unequality constraint" that acts as a
> counterpart to `~` (it does not seem quite straightforward how that
> would even work), but there is one way to encode it as a boolean type
> family `((n == 0) ~ 'False)`. That requires changing type families to
> patternmatch on `n == 0` instead of `n` directly, and possibly
> additional gymnastics to reflect the comparison at termlevel:
>
>
> type Index n l = IndexIf (n == 0) n l
>
> type family IndexIf (b :: Bool) (n :: Nat) (l :: [k]) :: k where
> IndexIf 'False n (x ': _ ) = x
> IndexIf 'True n (_ ': xs) = Index (n  1) xs
>
>
> Cheers,
> Liyao
>
> On 8/21/19 9:09 AM, Sylvain Henry wrote:
>> Hi,
>>
>> Suppose I have the following type family:
>>
>> type family Index (n :: Nat) (l :: [k]) = (r :: k) where
>> Index 0 (x ': _ ) = x
>> Index n (_ ': xs) = Index (n1) xs
>>
>> I'm using it to define a Variant type:
>>
>> data V2 (vs :: [k]) where
>> V2 :: forall vs (n :: Nat). KnownNat n => Proxy n > Index n vs
>> > V2 vs
>>
>> Now I want to match on the Variant retrieving either the head or the
>> tail (another Variant):
>>
>> splitV2 :: forall v vs. V2 (v:vs) > Either v (V2 vs)
>> splitV2 = \case
>> V2 (n1 :: Proxy n) v > case sameNat n1 (Proxy @0) of
>> Just Refl > Left v
>> Nothing > Right (V2 (Proxy @(n1)) v)
>>
>> It fails to typecheck with:
>>
>> Couldn't match type ‘Index n (v : vs)’ with ‘Index (n  1) vs’
>> Expected type: Index (n  1) vs
>> Actual type: Index n vs1
>> NB: ‘Index’ is a noninjective type family
>>
>>
>> Is there a way to make this work?
>>
>>
>> This is highly speculative as I'm not very familiar with
>> typechecking: would it be sound to make the inductive Index family
>> "weakly" injective? I.e. somehow produce a typing rule for the type
>> family:
>>
>> forall n n' x xs xs'.
>> Solving: Index n (x ': xs) ~ Index (n'1) xs'
>> Is equivalent to solving: if n /= 0 then (n ~ n', xs ~ xs') else
>> (x ~ Index (n'1) xs')
>>
>> Here we could know that "n /= 0" thanks to the match on "sameNat n1
>> (Proxy @0)".
>>
>> ("weakly" because we have some form of injectivity on the shape of
>> the list but not on its contents)
>>
>> Any pointer on this kind of stuff in research papers, Coq, Agda, etc. ?
>>
>> Thanks,
>> Sylvain
>>
>> _______________________________________________
>> HaskellCafe mailing list
>> To (un)subscribe, modify options or view archives go to:
>> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
>> Only members subscribed via the mailman list are allowed to post.
 next part 
An HTML attachment was scrubbed...
URL:
From allbery.b at gmail.com Thu Aug 22 10:16:39 2019
From: allbery.b at gmail.com (Brandon Allbery)
Date: Thu, 22 Aug 2019 06:16:39 0400
Subject: [Haskellcafe] Question on inductive typefamilies
InReplyTo: <5f958804f272a9daf790622e262a1069@haskus.fr>
References: <855bef4f071ae47ce89ca0d0b23a76e1@haskus.fr>
<159641df6a6a45b73618b80b3489d5f0@gmail.com>
<5f958804f272a9daf790622e262a1069@haskus.fr>
MessageID:
There are some plugins like natnormalise that help with this kind of thing.
ghc itself is not so good at these kinds of deductions.
On Thu, Aug 22, 2019 at 4:33 AM Sylvain Henry wrote:
> Hi Liyao,
>
> Thanks for your answer. Sadly I haven't managed to make it work this way
> neither.
>
> In addition I need a "KnownNat (n1)" while I only have "KnownNat n" (and
> the knowledge that n > 0). For the record, it works with an unsafeCoerce:
>
> data V2 (vs :: [k]) where
> V2 :: forall vs (n :: Nat). KnownNat n => Proxy n > Index n vs > V2
> vs
>
> splitV2 :: forall v vs. V2 (v:vs) > Either (V2 vs) v
> {# INLINE splitV2 #}
> splitV2 = \case
> V2 (n1 :: Proxy n) v > case sameNat n1 (Proxy @0) of
> Just Refl > Right v
> Nothing > case someNatVal (natVal n1  1) of
> SomeNat (n2 :: Proxy n') > case unsafeCoerce Refl :: Index n
> (v:vs) :~: Index n' vs of
> Refl > Left (V2 n2 v)
>
> instance Show (V2 '[]) where
> {# INLINABLE show #}
> show = undefined
>
> instance (Show x, Show (V2 xs)) => Show (V2 (x ': xs)) where
> {# INLINABLE show #}
> show v = case splitV2 v of
> Right x > show x
> Left xs > show xs
>
> test :: V2 '[Int,Word,String] > String
> test v = show v
>
> However the generated Core isn't as pretty as with the previous
> representation (which uses unsafeCoerce for the value, not for the index):
>
> data Variant (types :: [*]) = Variant {# UNPACK #} !Word Any
>
>
> I'll stick to this one for now.
>
> Sylvain
>
>
> On 21/08/2019 16:46, Liyao Xia wrote:
>
> Hi Sylvain,
>
> The problem is that in the case where `n1` is not equal to `0`, this
> unequality is not made available as a constraint solver (whereas in the
> case where they are equal, the `Refl` constructor makes the corresponding
> equality constraint available).
>
> In fact, there is no builtin "unequality constraint" that acts as a
> counterpart to `~` (it does not seem quite straightforward how that would
> even work), but there is one way to encode it as a boolean type family `((n
> == 0) ~ 'False)`. That requires changing type families to patternmatch on
> `n == 0` instead of `n` directly, and possibly additional gymnastics to
> reflect the comparison at termlevel:
>
>
> type Index n l = IndexIf (n == 0) n l
>
> type family IndexIf (b :: Bool) (n :: Nat) (l :: [k]) :: k where
> IndexIf 'False n (x ': _ ) = x
> IndexIf 'True n (_ ': xs) = Index (n  1) xs
>
>
> Cheers,
> Liyao
>
> On 8/21/19 9:09 AM, Sylvain Henry wrote:
>
> Hi,
>
> Suppose I have the following type family:
>
> type family Index (n :: Nat) (l :: [k]) = (r :: k) where
> Index 0 (x ': _ ) = x
> Index n (_ ': xs) = Index (n1) xs
>
> I'm using it to define a Variant type:
>
> data V2 (vs :: [k]) where
> V2 :: forall vs (n :: Nat). KnownNat n => Proxy n > Index n vs > V2
> vs
>
> Now I want to match on the Variant retrieving either the head or the tail
> (another Variant):
>
> splitV2 :: forall v vs. V2 (v:vs) > Either v (V2 vs)
> splitV2 = \case
> V2 (n1 :: Proxy n) v > case sameNat n1 (Proxy @0) of
> Just Refl > Left v
> Nothing > Right (V2 (Proxy @(n1)) v)
>
> It fails to typecheck with:
>
> Couldn't match type ‘Index n (v : vs)’ with ‘Index (n  1) vs’
> Expected type: Index (n  1) vs
> Actual type: Index n vs1
> NB: ‘Index’ is a noninjective type family
>
>
> Is there a way to make this work?
>
>
> This is highly speculative as I'm not very familiar with typechecking:
> would it be sound to make the inductive Index family "weakly" injective?
> I.e. somehow produce a typing rule for the type family:
>
> forall n n' x xs xs'.
> Solving: Index n (x ': xs) ~ Index (n'1) xs'
> Is equivalent to solving: if n /= 0 then (n ~ n', xs ~ xs') else (x ~
> Index (n'1) xs')
>
> Here we could know that "n /= 0" thanks to the match on "sameNat n1 (Proxy
> @0)".
>
> ("weakly" because we have some form of injectivity on the shape of the
> list but not on its contents)
>
> Any pointer on this kind of stuff in research papers, Coq, Agda, etc. ?
>
> Thanks,
> Sylvain
>
> _______________________________________________
> HaskellCafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
> Only members subscribed via the mailman list are allowed to post.
>
> _______________________________________________
> HaskellCafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
> Only members subscribed via the mailman list are allowed to post.

brandon s allbery kf8nh
allbery.b at gmail.com
 next part 
An HTML attachment was scrubbed...
URL:
From chrisdone at gmail.com Thu Aug 22 15:26:17 2019
From: chrisdone at gmail.com (Christopher Done)
Date: Thu, 22 Aug 2019 16:26:17 +0100
Subject: [Haskellcafe] Getting both the value and name of a variable in
one expression
InReplyTo:
References:
MessageID:
I considered an expressionwithinanexpression but thought a
stagerestriction would break it. Maybe not! Let me go test it!
On Wed, 21 Aug 2019 at 17:31, Michael Sloan wrote:
> One potential solution here is to have checkGrammar_take2 return an
> expression which returns an expression. I haven't tried compiling
> this, but something roughly like:
>
> checkGrammar_2 name = [ if valueFine $(varE name) then varE name else
> error "value isn't fine" ]
>
> Then it'd be used like $($(checkGrammar_2 'thename)). The thorphans
> package can also be useful for this because it provides Lift instances
> for the TH AST.
>
> Michael
>
> On Tue, Aug 20, 2019 at 10:36 AM Christopher Done
> wrote:
> >
> > Hi all,
> >
> > Do we have already a syntax for ‘foo that also contains the typed value
> like TExp?
> >
> > I have e.g. an AST that I want to do more static checks on it that
> aren’t as convenient to do in the type system. Here’s an example:
> >
> >   Check the grammar spec to produce a grammar.
> > checkGrammar :: (SchemaName, [(SchemaName, Schema)]) > Q Exp
> > checkGrammar (toplevel, rules) =
> > if M.size rulesMap /= length rules
> > then error "Duplicate rule names in grammar."
> > else lift (Grammar {grammarToplevel = toplevel, grammarRules =
> rulesMap})
> > where
> > rulesMap = M.fromList rules
> >
> >   Grammar for Haskell.
> > grammar :: Grammar
> > grammar = $(checkGrammar $ runDefine $ mdo
> >  General expression
> > expression < rule "Expression" (ChoiceSchema [variable,
> constructor, parentheses
> > ,tuple, let',
> application, string])
> > application < rule "Application" (CompositeSchema [expression,
> expression])
> > parentheses < rule "Parentheses" (CompositeSchema
> [openParenSchema, expression, closeParenSchema])
> >
> > ...
> > pure expression)
> >
> > Here I do a trivial check for duplicates. After I’ve checked the
> > expression at compiletime, I Lift it so that it can be used at
> > runtime. That’s pretty good. But some types like (a > b) don’t Lift. So
> > an alternative would be:
> >
> > grammar = $(checkGrammar_take2 thename 'thename)
> >
> > In which checkGrammar_take2 would:
> >
> > Use thename at compiletime for a check.
> > If the check passes, then return (VarE thename)
> >
> > E.g.
> >
> > checkGrammar_take2 value name = if valueFine value then varE name else
> > error "value isn't fine"
> >
> > That’s actually quite a good solution because it avoids a lift, and I
> > didn’t transform the AST. It’s also more efficient than lifting.
> >
> > But there’s no checked relationship between thename and ‘thename.
> > checkGrammar_take2 has no way of knowing that they refer to the same
> > thing. See?
> >
> > Hence, if I could get e.g. `thename to produce both the value and a
> > name for the value, that would be cool. My gist doesn’t go this
> > far. It might look like this:
> >
> > checkGrammar_take2 namedValue = if valueFine (getValue namedValue) then
> getExp namedValue else error "value isn't fine"
> >
> > and call it like:
> >
> > mygrammar = checkGrammar_take2 `thename
> >
> > So the semantics would be roughly similar to
> >
> > [ thename ] :: TExp a
> >
> > but you’d get
> >
> > `thename :: Named a
> >
> > where
> >
> > data Named a = { namedThing :: a, nameOfThing :: Name }
> >
> > I feel like the more DSLs I design, the more I’d like something like
> this to perform my static checks.
> >
> > Cheers,
> >
> > Chris
> >
> > _______________________________________________
> > HaskellCafe mailing list
> > To (un)subscribe, modify options or view archives go to:
> > http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
> > Only members subscribed via the mailman list are allowed to post.
>
 next part 
An HTML attachment was scrubbed...
URL:
From chrisdone at gmail.com Thu Aug 22 15:40:34 2019
From: chrisdone at gmail.com (Christopher Done)
Date: Thu, 22 Aug 2019 16:40:34 +0100
Subject: [Haskellcafe] Getting both the value and name of a variable in
one expression
InReplyTo:
References:
MessageID:
Hurray! It works!
{# LANGUAGE TemplateHaskell #}import
Language.Haskell.TH.Syntaximport Language.Haskell.THimport
Language.Haskell.TH.Lift ()
valueFine :: String > BoolvalueFine = not . null
checkGrammar_2 :: Name > ExpQcheckGrammar_2 name =
[ if valueFine $(varE name)
then varE name
else error "value isn't fine" ]
thename :: [Char]thename = "Hello!"
thename_empty :: [Char]thename_empty = ""
The output:
> :t $(checkGrammar_2 'thename)
$(checkGrammar_2 'thename) :: ExpQ
> :t $($(checkGrammar_2 'thename))
$($(checkGrammar_2 'thename)) :: [Char]
> $($(checkGrammar_2 'thename))"Hello!"
> $($(checkGrammar_2 'thename_empty))
:49:1: error:
• Exception when trying to run compiletime code:
value isn't fineCallStack (from HasCallStack):
error, called at :49:5 in interactive:Ghci2
Code: (if valueFine thename_empty then
varE
((Name (mkOccName "thename_empty"))
(((NameG VarName) (mkPkgName "main")) (mkModName "Main")))
else
error "value isn't fine")
• In the untyped splice: $($(checkGrammar_2 'thename_empty))
Thanks Michael! You’re a star!
I should document this in a gist or blog post or something as a technique
for DSL checking.
On Thu, 22 Aug 2019 at 16:26, Christopher Done wrote:
> I considered an expressionwithinanexpression but thought a
> stagerestriction would break it. Maybe not! Let me go test it!
>
> On Wed, 21 Aug 2019 at 17:31, Michael Sloan wrote:
>
>> One potential solution here is to have checkGrammar_take2 return an
>> expression which returns an expression. I haven't tried compiling
>> this, but something roughly like:
>>
>> checkGrammar_2 name = [ if valueFine $(varE name) then varE name else
>> error "value isn't fine" ]
>>
>> Then it'd be used like $($(checkGrammar_2 'thename)). The thorphans
>> package can also be useful for this because it provides Lift instances
>> for the TH AST.
>>
>> Michael
>>
>> On Tue, Aug 20, 2019 at 10:36 AM Christopher Done
>> wrote:
>> >
>> > Hi all,
>> >
>> > Do we have already a syntax for ‘foo that also contains the typed value
>> like TExp?
>> >
>> > I have e.g. an AST that I want to do more static checks on it that
>> aren’t as convenient to do in the type system. Here’s an example:
>> >
>> >   Check the grammar spec to produce a grammar.
>> > checkGrammar :: (SchemaName, [(SchemaName, Schema)]) > Q Exp
>> > checkGrammar (toplevel, rules) =
>> > if M.size rulesMap /= length rules
>> > then error "Duplicate rule names in grammar."
>> > else lift (Grammar {grammarToplevel = toplevel, grammarRules =
>> rulesMap})
>> > where
>> > rulesMap = M.fromList rules
>> >
>> >   Grammar for Haskell.
>> > grammar :: Grammar
>> > grammar = $(checkGrammar $ runDefine $ mdo
>> >  General expression
>> > expression < rule "Expression" (ChoiceSchema [variable,
>> constructor, parentheses
>> > ,tuple, let',
>> application, string])
>> > application < rule "Application" (CompositeSchema [expression,
>> expression])
>> > parentheses < rule "Parentheses" (CompositeSchema
>> [openParenSchema, expression, closeParenSchema])
>> >
>> > ...
>> > pure expression)
>> >
>> > Here I do a trivial check for duplicates. After I’ve checked the
>> > expression at compiletime, I Lift it so that it can be used at
>> > runtime. That’s pretty good. But some types like (a > b) don’t Lift. So
>> > an alternative would be:
>> >
>> > grammar = $(checkGrammar_take2 thename 'thename)
>> >
>> > In which checkGrammar_take2 would:
>> >
>> > Use thename at compiletime for a check.
>> > If the check passes, then return (VarE thename)
>> >
>> > E.g.
>> >
>> > checkGrammar_take2 value name = if valueFine value then varE name else
>> > error "value isn't fine"
>> >
>> > That’s actually quite a good solution because it avoids a lift, and I
>> > didn’t transform the AST. It’s also more efficient than lifting.
>> >
>> > But there’s no checked relationship between thename and ‘thename.
>> > checkGrammar_take2 has no way of knowing that they refer to the same
>> > thing. See?
>> >
>> > Hence, if I could get e.g. `thename to produce both the value and a
>> > name for the value, that would be cool. My gist doesn’t go this
>> > far. It might look like this:
>> >
>> > checkGrammar_take2 namedValue = if valueFine (getValue namedValue) then
>> getExp namedValue else error "value isn't fine"
>> >
>> > and call it like:
>> >
>> > mygrammar = checkGrammar_take2 `thename
>> >
>> > So the semantics would be roughly similar to
>> >
>> > [ thename ] :: TExp a
>> >
>> > but you’d get
>> >
>> > `thename :: Named a
>> >
>> > where
>> >
>> > data Named a = { namedThing :: a, nameOfThing :: Name }
>> >
>> > I feel like the more DSLs I design, the more I’d like something like
>> this to perform my static checks.
>> >
>> > Cheers,
>> >
>> > Chris
>> >
>> > _______________________________________________
>> > HaskellCafe mailing list
>> > To (un)subscribe, modify options or view archives go to:
>> > http://mail.haskell.org/cgibin/mailman/listinfo/haskellcafe
>> > Only members subscribed via the mailman list are allowed to post.
>>
>
 next part 
An HTML attachment was scrubbed...
URL:
From chrisdone at gmail.com Thu Aug 22 16:09:06 2019
From: chrisdone at gmail.com (Christopher Done)
Date: Thu, 22 Aug 2019 17:09:06 +0100
Subject: [Haskellcafe] Getting both the value and name of a variable in
one expression
InReplyTo:
References:
MessageID:
Depending on how much syntactic overhead you’re happy with, you can go full
typesafe:
checkGrammar_3 :: Q (TExp String) > Q (TExp (Q (TExp
String)))checkGrammar_3 q = do
TExp expr < q
[ if valueFine $$(q)
then pure (TExp expr)
else error "value is not fine" ]
> $$($$(checkGrammar_3 [ thename ]))"Hello!"
> $$($$(checkGrammar_3 [ thename_empty ]))
:45:4: error:
• Exception when trying to run compiletime code:
value is not fine
In my case it might even be a fine tradeoff, because I’m favoring THbased
validation of a DSL where doing it with e.g. typelevel lists and type
families has worse typeinference and a higher price to pay in
typesignatures. So I can make a “staticsmart” constructor that looks more
like:
checkGrammar_3 :: Q (TExp (Tree a)) > Q (TExp (Q (TExp (ValidTree
a))))useValidTree :: ValidTree a > ...
So you pay the cost once here, but when building the tree, which is more
larger code, you don’t pay any cost, and there’s where it matters.
On Thu, 22 Aug 2019 at 16:40, Christopher Done wrote:
> Hurray! It works!
>
> {# LANGUAGE TemplateHaskell #}import Language.Haskell.TH.Syntaximport Language.Haskell.THimport Language.Haskell.TH.Lift ()
> valueFine :: String > BoolvalueFine = not . null
> checkGrammar_2 :: Name > ExpQcheckGrammar_2 name =
> [ if valueFine $(varE name)
> then varE name
> else error "value isn't fine" ]
> thename :: [Char]thename = "Hello!"
> thename_empty :: [Char]thename_empty = ""
>
> The output:
>
> > :t $(checkGrammar_2 'thename)
> $(checkGrammar_2 'thename) :: ExpQ
> > :t $($(checkGrammar_2 'thename))
> $($(checkGrammar_2 'thename)) :: [Char]
> > $($(checkGrammar_2 'thename))"Hello!"
> > $($(checkGrammar_2 'thename_empty))
>
> :49:1: error:
> • Exception when trying to run compiletime code:
> value isn't fineCallStack (from HasCallStack):
> error, called at