00:17
DataComputist joined
00:27
<geppettodivacin>
@tell shoglok I added a potentially better exit condition to your code. http://lpaste.net/7609497281783398400
00:27
<lambdabot>
Consider it noted.
00:27
<geppettodivacin>
@tell shoglok Feel free to ask about it when you return.
00:27
<lambdabot>
Consider it noted.
00:41
<parsnip>
having some trouble matching items in "[hello:\"world\" add:\"1\"]\n[hello:\"end space\" add:\"2\"]\n"
00:41
<parsnip>
using Parsec
00:42
<parsnip>
i think i need to make sure i'm matching items like "\"end space\"" correctly
00:42
<parsnip>
i'm thinking to use a `between (string "\"") (string "\"") anyChar`
00:43
<monochrom>
But anyChar will eat your closing quotes.
00:43
<parsnip>
er, (many anyChar)
00:43
<monochrom>
you will need noneOf.
00:44
<parsnip>
maybe a lookAhead?
00:45
<monochrom>
No, lookAhead and notFollowedBy will complicate the matter.
00:45
<parsnip>
that fixes that parse, yes
00:46
<parsnip>
but i may encounter other escaped items in the string, like \' i think
00:47
<monochrom>
noneOf "\"'"
00:47
<monochrom>
or equivalently, noneOf [ '"', '\'' ]
00:48
<parsnip>
monochrom: wouldn't that skip \', i need to eat it so users can have \' in the value
00:49
<parsnip>
https://taskwarrior.org/docs/escapes.html
00:50
<monochrom>
I don't understand the question, but you now know of noneOf and you can control how many levels of ecaping you need.
00:50
<parsnip>
hmm, yeah, i guess i can wait till i see it actually break
01:38
<parsnip>
monochrom: ooohhhh, i did not realize \" was a single char, i can simply do the noneOf, sorry for not seeing that! >.<
01:45
uglyfigurine joined
02:10
uglyfigurine joined
02:12
DataComputist joined
02:43
<mounty>
I'm thinking about setting up CI for a Haskell project; do people generally use Jenkins/Hudson or is there a more Haskellish solution?
03:28
<mounty>
There is Bake but it appears to be abandoned, regrettably.
03:38
exferenceBot joined
04:11
DataComputist joined
06:04
DataComputist joined
06:05
DataComputist joined
06:09
DataComputist joined
06:15
DataComputist joined
06:17
DataComputist joined
06:17
DataComputist joined
06:18
DataComputist joined
06:40
DataComputist joined
06:46
ThomasLocke_ joined
06:46
ThomasLocke_ joined
06:48
DataComputist joined
06:49
DataComputist joined
07:22
DataComputist joined
07:24
DataComputist joined
07:33
DataComputist joined
07:45
DataComputist joined
08:10
DataComputist joined
08:13
DataComputist joined
08:18
DataComputist joined
08:22
DataComputist joined
08:31
DataComputist joined
08:46
DataComputist joined
08:49
DataComputist joined
08:52
DataComputist joined
08:59
DataComputist joined
08:59
<dmj`>
mounty: hydra and nixos are nice, if you dont’ want to use nix, circle ci and stack are nice
09:00
DataComputist joined
09:19
DataComputist joined
09:22
DataComputist joined
09:22
DataComputist joined
09:33
DataComputist joined
09:41
DataComputist joined
10:03
DataComputist joined
10:10
<mounty>
Thanks dmj`; I'll have a look.
10:10
<dmj`>
if this is an open source project, travis and the ghc build matrix might work well
10:12
<cydo>
Hi! I'm leaning haskell with the haskell book and have a question
10:12
<mounty>
I'd have to check the licence there because although it's open-source now, I intend to capitalise on it and offer consultancy services.
10:12
<cydo>
How is it possible that "4 :: Product Int" is actually recognized as a product?
10:13
DataComputist joined
10:13
<dmj`>
cydo: Product might have a Num constraint
10:13
<dmj`>
Num a => Product a
10:14
<cydo>
So, fromInteger is automatically applied in this case?
10:14
<dmj`>
Num a => Num (Product a)
10:14
<dmj`>
newtype MyInt = MyInt Int deriving (Num)
10:15
<dmj`>
will typecheck
10:15
<cydo>
oh ok, I did not know you could derive Num
10:15
<cydo>
awesome, thank you :)
10:15
<dmj`>
caveat emptor
10:15
<cydo>
but how does the compiler know to use fromInteger here? is is built-in the language?
10:15
<cydo>
or is there a feature allowing conversion
10:16
<dmj`>
cydo: what is the type of fromInteger ?
10:16
<cydo>
Integer -> a
10:16
<dmj`>
fromInteger :: Num a => Integer -> a
10:17
<dmj`>
you’ll need an extension too
10:17
<dmj`>
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
10:18
<merijn>
cydo: fromInteger is part of the Num typeclass
10:19
<mounty>
Travis and Circle CI are both hosted services. I've set up a Jenkins server at work so am happy to do so again and obtain the benefits of complete control.
10:19
<mounty>
In any case, the hassle of setting-up the CI is as nothing compared with the hassle of actually writing the tests.
10:19
<cydo>
but what if there were two functions in the typeclass with the same signature?
10:19
<merijn>
cydo: And the language reports explicitly defines numeric literals to be polymorphic
10:19
<lambdabot>
Num t => t
10:19
<dmj`>
cydo: it’s inheriting the Num instance from Int
10:19
<cydo>
aaah right, that was the missing piece
10:19
<cydo>
thank you, i get it
10:19
<merijn>
cydo: The report specifies the numeric literal 4 is equivalent to 'fromInteger 4' :)
10:20
<merijn>
The nice thing is that this means literals automagically work if you define a new Num instance :)
10:20
<merijn>
If, instead of using the extension dmj` mentioned, you just wrote a Num instance by hand it'd "Just Work (TM)"
10:20
<cydo>
this is really really cool
10:21
<cydo>
haskell is really impressive
10:22
DataComputist joined
10:22
<merijn>
There's a few warts with the system (such as dealing with overflow, negative numbers, etc.) but overall it's nice
10:23
<cydo>
this makes usage of integer monoids a bit simpler though
10:23
<cydo>
not sure if I will ever need them in real code, but still
10:24
<merijn>
cydo: Not often, but they crop occasionally in useful things
10:24
<dmj`>
cydo: you’ll soon be surprised what you find to be “necessary” in real code
10:24
<cydo>
do you have any example in mind?
10:25
<cydo>
well, I find it a bit hard to reason with abstractions in mind for now
10:25
<cydo>
so not sure if I would be able to use them for awesome code :)
10:26
<merijn>
cydo: Counting occurences of a certain type in a list using "Map k (Sum Integer)"
10:27
<merijn>
Simply "map (, Sum 1)" over the list and then a fold that mappends elements
10:28
<merijn>
I think I actually wrote a newtype for Map to use a different Monoid. The default is "Ord k => Monoid (Map k v)"
10:28
<merijn>
But I wanted "(Ord k, Monoid v) => Monoid (Map k v)"
10:28
DataComputist joined
10:28
<merijn>
Then you can simply mappend a list of singleton maps :)
10:29
<cydo>
in this case, can you still keep the benefits from the standard library Data.Monoid?
10:29
<cydo>
or do you have to "rewrite" all functions you need?
10:29
<merijn>
cydo: All the stuff in Data.Monoid works for any Monoid, that's the nice thing
10:29
<merijn>
Actually, lemme propose a newtype for this...
10:30
<cydo>
so the map, now being a Monoid can automatically do a frequency map...
10:30
<cydo>
that's quite incredible
10:30
<merijn>
cydo: Map is already a monoid, but not that one I'd want. By default it's a left-biased union
10:31
<merijn>
But by newtyping and giving a new Monoid instance for the newtype, yes, that works
10:31
<cydo>
yay i get it
10:31
<cydo>
i wonder if I will ever be able to get a job in Haskell
10:31
<cydo>
not sure if there are so many :(
10:32
<cydo>
but the language is so challenging and good
10:32
<cydo>
I'm having a lot of fun learning it!
10:34
DataComputist joined
10:35
<Geekingfrog>
What logging library would you recommend? I'm looking at https://github.com/wdanilo/haskell-logger , the last commit is over a year ago and I don't know if it's because it's done or abandonned :/
10:37
DataComputist joined
10:44
DataComputist joined
10:51
DataComputist joined
10:54
<Akii>
I'm doing it wrong
10:54
<Akii>
just thought "hey I need something to try a MonadError and if it fails just recover"
10:55
<Akii>
and it's already defined catchError :: m a -> (e -> m a) -> m a
11:03
<jle`>
Geekingfrog: i''ve been happy with monad-logger
11:06
<Geekingfrog>
logging-effect looks quite nice as well.
11:22
DataComputist joined
11:23
DataComputist joined
11:23
DataComputist joined
11:23
DataComputist joined
11:24
DataComputist joined
11:25
DataComputist joined
11:33
netheranthem joined
11:50
<Geekingfrog>
I'm looking at the source of partitionEithers (http://hackage.haskell.org/package/base-4.9.1.0/docs/src/Data.Either.html#partitionEithers) and I'm confused by the pattern ~(l, r). What is that ?
11:51
<merijn>
Lazy pattern match
11:51
<merijn>
i.e., one that isn't evaluated until l or r are used
11:51
<merijn>
> case undefined of (l, r) -> "Whoo!"
11:51
<lambdabot>
"*Exception: Prelude.undefined
11:51
<merijn>
> case undefined of ~(l, r) -> "Whoo!"
11:51
<lambdabot>
"Whoo!"
11:52
<merijn>
> case undefined of ~(l, r) -> "Whoo!" ++ l
11:52
<lambdabot>
"Whoo!*Exception: Prelude.undefined
11:52
<merijn>
> case undefined of (l, r) -> "Whoo!" ++ l -- final one
11:52
<lambdabot>
"*Exception: Prelude.undefined
11:52
<Geekingfrog>
Why is the lazy pattern matching required for partitionEithers ?
11:55
<merijn>
Honestly, I'm not sure
12:17
<hexagoxel>
> bimap (take 1) (take 1) $ partitionEithers [Left 1, Right 1, undefined]
12:17
<lambdabot>
([1],[1])
12:17
<hexagoxel>
> bimap (take 1) (take 1) $ partitionEithers' [Left 1, Right 1, undefined]
12:17
<lambdabot>
(*Exception: Prelude.undefined
12:19
<hexagoxel>
Geekingfrog: the latter is without lazy pattermatch. it is strict in the input by forcing (,).
12:20
<Geekingfrog>
Cool. Not sure exactly what's going on but I'll dig in.
12:27
<hexagoxel>
Geekingfrog: `either left right` takes in an `Either a b` and a tuple. if the tuple is forced, you force "the next iteration" because the tuple constructor is in `left`/`right`, and forcing that means we look at the next input element. and so on.
12:27
<hexagoxel>
the way the tuple is constructed/destructed means that without lazy pattermatch, you get the effects of a foldr'.
13:21
mizu_no_oto_work joined
13:23
<drewr>
mounty: not really haskelly per se, but https://concourse.ci/ is nice
13:40
emmanuel_erc joined
15:01
uglyfigurine joined
15:03
uglyfigurine joined
15:04
<Akii>
what type do I use to get reliable floats in Haskell?
15:08
<benzrf>
Akii: what do yu mean by reliable?
15:09
<merijn>
Akii: Did you mean "I want perfect precision"?
15:09
<Akii>
having reliable addition fx.
15:09
<merijn>
What do you mean by reliable?
15:09
<Akii>
no rounding mistakes and the like
15:09
<merijn>
Float is perfectly reliable, but only if your model is IEEE754 floating point, not if your model is "rationals"
15:10
<merijn>
Akii: Will rationals do? Or do you need reals?
15:10
<Akii>
I'll have to look into what rationals are ^^
15:10
<Akii>
thanks for the pointer
15:10
<Akii>
benzrf: did you get my link to my domain problem yesterday?
15:10
<merijn>
Akii: Rationals are all numbers that can be represented by 1) a fraction or 2) a finite number of decimals
15:10
<benzrf>
Akii: ah, no sorry
15:10
<merijn>
Well, I suppose those are the same thing :p
15:10
<Akii>
because I'm going crazy
15:11
<benzrf>
Akii: you don't want floats
15:11
<merijn>
Akii: For example, pi is a real, not a rational since it's infinite length
15:11
<merijn>
(and not a fraction)
15:11
<Akii>
benzrf: http://lpaste.net/353855
15:11
<benzrf>
floats are explicitly fixed-precision, so by definition you won't have reliable math
15:11
<benzrf>
you want some kind of fractional type, but that's more general than "float"
15:11
<benzrf>
merijn: a fraction of integers
15:11
<benzrf>
pi is certainly equal to 3pi/3
15:11
<merijn>
Akii: Can you describe what you're trying to represent? :)
15:12
<Akii>
merijn: User provides a number that contains a comma; I need to sum that
15:12
<Akii>
and idk how many problems we had with this
15:12
<merijn>
ok, then Rational will work :)
15:12
<Akii>
kay, will try those out. thanks!
15:12
<merijn>
Since your user, presumably, is not allowed to enter infinite length numbers :p
15:12
<merijn>
> 1 % 3 + 2 % 3
15:14
<Akii>
hehe "{\"numerator\":13,\"denominator\":10}"
15:14
<Akii>
just converted that to JSON
15:14
<Akii>
to see what happens
15:19
<Akii>
benzrf: if anything is unclear or if it's just too much just let me know ^^
15:30
<* Akii>
scares away anyone with bad domain logic
15:32
uglyfigurine joined
15:49
<nitrix>
:t kemonomimify "Akii" Kitty
15:49
<nitrix>
Not bad, now I need to figure the same thing with dependent types and obtain an `Animal Cat` :D
15:51
<Akii>
I need a lenses crashcourse
15:51
<Akii>
might be something for the weekend
15:54
<Akii>
dafuq is kemonomimify
16:02
<nitrix>
:t kemonomimify
16:02
<lambdabot>
Human -> Ears -> Animal
16:03
<nitrix>
It turns a Human into an Animal by adding the ears of your choice.
16:05
<nitrix>
Had I been more cleaver, I would've made it produce a URL instead of bottom.
16:13
<openheavens>
Could anyone please explain to me how to identify an expression in Weak Head Normal Form?
16:20
<nitrix>
openheavens: It's in weak-head normal form if it cannot be reduced further.
16:20
<nitrix>
openheavens: Is `42` NF or WHNF ?
16:20
<openheavens>
I understand that 42 is both NF and WHNF
16:21
<openheavens>
because 42 cannot be reduced further
16:21
<nitrix>
As far as I know, 42 is normal form.
16:21
<nitrix>
openheavens: Yes and this extends to data constructors as well as lambdas.
16:22
<nitrix>
Just 42 is normal form, (0, 0) is normal form, so is \x -> x + 1
16:23
<nitrix>
openheavens: Notice how `Just 42` cannot be reduced further, neither can `(0, 0)` be reduced further and same with the lambda as we have nothing to apply it on.
16:23
<nitrix>
openheavens: `(\x -> x + 1) 42` would be WHNF.
16:24
<nitrix>
As you obtain a thunk representing the computation that is applying the lambda to 42, the computation can be further reduced by doing the application.
16:25
<nitrix>
Same with 1 + 1, it's WHNF and 'h' : "askell", both are weak head normal forms as they can be reduced further.
16:25
<nitrix>
openheavens: Does this helps?
16:26
<openheavens>
yes, it does.. Thank you very much
16:28
<nitrix>
openheavens: Normally I don't bring up thunks because it's an operational concept of GHC inner workings, but lazy evaluation essentially relies on it.
16:28
<nitrix>
openheavens: https://i.stack.imgur.com/1leiT.png
16:29
<openheavens>
understood. The image makes things clearer.
16:31
<nitrix>
openheavens: I prefer the earlier examples but I know that image works for some and their mental blockers :P
16:42
<glguy>
`(\x -> x + 1) 42` is *not* WHNF
16:42
<glguy>
but maybe I'm misreading the backlog
16:43
<glguy>
Also: 1 + 1 isn't WHNF
16:45
<glguy>
Weak head normal form doesn't mean "can be reduced further"
16:47
<nitrix>
glguy: If we ignore HNF, I'd like to know where I'm mistaken.
16:48
<nitrix>
As far as Haskell is concerned, `1+1` and `(\x -> x + 1) 42` should clearly not be NF, which only leaves WHNF. HNF is irrelevant for Haskell, unless very specific cases like `seq`.
16:48
<glguy>
nitrix: Start here https://wiki.haskell.org/Weak_he…
16:48
<glguy>
https://wiki.haskell.org/Weak_head_normal_form
16:48
<glguy>
There are the 3 bullets of things that are WHNF
16:48
<nitrix>
glguy: I've read the material so reading it once more will probably lead me to the same conclusion.
16:48
<nitrix>
glguy: Mind explaining where I went wrong?
16:49
<glguy>
A lambda applied to an argument is not going to be WHNF since the outermost constructor isn't known
16:50
<glguy>
so Just (1+1) is WHNF
16:50
<glguy>
the outermost constructor is known, but it's in in NF as there are stuff left to reduce, the 1+1
16:51
<Geekingfrog>
you mean *not* in NF I guess ?
16:51
<glguy>
everything that is NF is WHNF
16:51
<srhb>
s/in in/not in/
16:51
<glguy>
yeah, in in -> not in
16:52
<nitrix>
glguy: Just (1+1) is WHNF, I agree. Do you have other examples?
16:52
<glguy>
Of things that *are* WHNF?
16:52
<srhb>
nitrix: I'm not sure, but something you said lead me to think you are trying to shoehorn all things into being either in NF or WHNF while they can be neither.
16:53
<nitrix>
srhb: What's an example of "neither" that still applies to Haskell?
16:53
<glguy>
1+1 is neither WHNF nor NF
16:53
<nitrix>
glguy: Whichever, see if you definition matches with mine until we find where my misunderstanding is.
16:53
<glguy>
ok, so we agree that 1+1 is neither?
16:54
<glguy>
and (\x -> x + 1) 42 is neither WHNF nor NF
16:54
<nitrix>
glguy: How about (+1) 1 1
16:54
<nitrix>
glguy: How about (+) 1 1
16:54
<glguy>
that's exactly the same as 1+1, neither
16:54
<Geekingfrog>
isn't that the same as 1 + 1 ?
16:54
<glguy>
(+) is not a constructor
16:54
<glguy>
or a built-in function applied to too few arguments
16:55
<glguy>
or a lone lambda
16:55
<nitrix>
That is so freaking arbitrary.
16:55
<nitrix>
Haskell is messed up.
16:55
<glguy>
(+) computes, You can't match on it, it's different from constructors
16:55
<glguy>
It's not arbitrary at all
16:56
<nitrix>
You're supposed to be able to reduce (1 + 2 + 3) in which ever order, (1 + (2 + 3)) or ((1 + 2) + 3), and obtain the same normal form 6.
16:56
<glguy>
constructors are distinct elements not equal to any other constructors
16:56
<nitrix>
And these are supposed to be WHNF.
16:56
<glguy>
The fact that + is associative isn't a general requirement of functions in Haskell
16:56
<nitrix>
I don't know why Haskell is begging to differ or bend the terminology.
16:56
<glguy>
and no terminology is being bent
16:57
<glguy>
It's true that whether you reduce: ((1+2)+(3+4)) as (3+(3+4)) or ((1+2)+7) that you get the same answer
16:57
<hs428>
nitrix: If you have integers WHNF and NF are exactly the same, only the result can be WHNF or NF
16:58
<hs428>
that is with the usual integer definition anyway
16:58
<nitrix>
I think that's a sign I need to invest time in other programming languages.
16:58
<glguy>
and none of these are WHNF : (1 + 2 + 3) (1 + (2 + 3)) or ((1 + 2) + 3)
16:58
<nitrix>
That's ridiculous.
16:58
<merijn>
nitrix: What is?
16:59
<hs428>
WHNF means that the "top" part of the expression is already evaluated
16:59
<hs428>
oh well, he's gone
16:59
<Geekingfrog>
ragequit over WHNF ?
17:00
<srhb>
Frustration happens..
17:47
uglyfigurine joined
17:49
<nokomo>
what does ."dot" mean here " 𝜆𝑥.𝑥 " ? does . represent the begining of the body of the function?
17:50
<glguy>
The syntax is: 'λ' [variable binders] '.' [expression]
17:51
<nokomo>
thank you glguy
17:56
mizu_no_oto_work joined
17:57
uglyfigurine joined
17:58
<nokomo>
i dont know what kind of feelings this question might stir, but, do you guys think that writing a server application in haskell that handles websockets would be a painful experience?
17:59
<srhb>
nokomo: Compared to what? (No, I think it would be enjoyable and fun.)
17:59
<srhb>
I also think it's highly subjective.
17:59
<nokomo>
Go or PHP, but mainly Go
18:00
<srhb>
nokomo: Well, personally -- and my opinion is par excellence -- those both suck majorly.
18:00
<Akii>
oh my, I should've looked into lenses earlier
18:00
<nokomo>
yeah it is subjective, im sorry for that, im just afraid of getting burned like when I switched to Go
18:01
<Akii>
nokomo: not painful at all actually
18:01
<srhb>
nokomo: Take it as a learning experience if you can afford regretting it, otherwise don't.
18:01
<Akii>
already did that
18:13
mizu_no_oto_work joined
18:14
<Cale>
nokomo: As someone who does that professionally (develops web applications which include backends that manage websockets), not especially so.
18:16
<nokomo>
Cale, which is the most commonly used webserver in haskell? as I see there are a few options
18:17
<Cale>
Yeah, there are a few frameworks, and it's generally possible to mix and match parts of them even.
18:17
<Cale>
We use Snap where I'm working -- it's not perfect, and frankly in many ways it's overkill given that we only develop single page applications that use reflex-dom on the frontend.
18:18
<Cale>
But it's pretty reasonable
18:18
<Cale>
There's also Happstack, which is generally pretty good.
18:19
<srhb>
Happstack was what I initially touched years ago, it was very enjoyable.
18:20
<Cale>
and then Yesod and Scotty, which are both based on the Warp webserver, but have rather different approaches to things
18:21
<Cale>
Yesod is very much inspired by Rails, and is pretty "heavy" in the sense of making a lot of decisions for you up front -- it has lots of Template Haskell based mini-languages for configuring things, and well, some people love those, and others are not as crazy about them.
18:22
<srhb>
As Warp-based ones go, servant is pretty worthy of a mention these days.
18:22
<srhb>
(Thought pretty specialized)
18:22
<Akii>
Servant is so good :o
18:22
<srhb>
I need to try servant-subscriber sometime for the websockets...
18:23
<Cale>
nokomo: But yeah, you can shop around for various frameworks, but the webservers themselves at the heart of them are all pretty good.
18:24
<srhb>
Did they "new" Happstack server ever materialize? I forget what it was called.
18:25
<Cale>
nokomo: I will say that we did run into some issues with the websockets library under concurrent load testing, and I'm uncertain about the status of them upstream now. The manner in which I fixed them wouldn't really make for a nice PR.
18:25
<nokomo>
thanks for the heads-up though
18:27
<Cale>
https://github.com/obsidiansystems/websockets https://github.com/obsidiansystems/websockets-snap have my changes
18:27
<Akii>
Cale: what issues specifically?
18:28
<Cale>
Specifically, there was a race condition involving a pair of MVars... let me look at the diff here and remind myself
18:29
<Cale>
https://github.com/jaspervdj/websockets/blob/master/src/Network/WebSockets/Stream.hs#L65
18:31
DataComputist joined
18:34
<Cale>
There's two MVars here, sendLock and receiveLock, and an IORef which tells you whether the stream is supposed to be closed. It's possible to take both of those locks at once, have both the send and receive ends get past the assertNotClosed, and then... dang, I can't quite remember what the case was that caused things to go terribly
18:34
<Akii>
what was the result?
18:34
<Akii>
or like, the error
18:37
<Cale>
The result was something going wrong with the incremental parser -- parses failing when they shouldn't
18:38
<Cale>
Sorry I can't remember the details better, this was last October now :)
18:38
<Akii>
np, didn't run into such problems yet
18:38
<Akii>
fortunately :D
18:38
<Cale>
It only happened once we started doing load testing
18:39
<Cale>
It was extremely rare otherwise
18:39
<Akii>
I've no load so np
18:41
<Cale>
Probably it would be worth taking the time to go through and really do a more careful and thorough re-work of the library using pipes. I just sort of jammed pipes in there and ripped out the hacky custom Stream type, as I'd already spent the better part of a week trying to track down why we were seeing things fail under load, and that fixed the issue nicely, so I just left it at that.
18:42
<Akii>
don't even know how to use pipes yet xD
18:42
<Cale>
I don't either, lol.
18:42
<Cale>
(well, that's a bit of a lie)
18:43
<Cale>
Pipes is really very nice in a lot of ways, when you need that kind of thing. I think it's prettier than conduit and the various other streaming libraries.
18:44
<Cale>
But it's still kinda crazy.
18:44
<Akii>
lenses I can get to work with a bit imagination.. but that stuff
18:44
<Cale>
It's better than it looks, once you actually start writing things.
18:50
<nil_>
Is Monad strictly more powerful than ArrowChoice?
18:55
<benzrf>
nil_: arrowchoice on what type
18:57
<nil_>
You mean the question doesn't make sense without a concrete type?
18:57
<Cale>
Yes. It's ArrowApply which gets you Monad
19:00
<benzrf>
nil_: well, you're comparing apples and oranges i guess
19:00
<benzrf>
nil_: it makes sense to compare Applicative and Monad without additional information, because they can be applied to the same type
19:00
<benzrf>
but ArrowChoice and Monad take types of different kinds
19:01
<benzrf>
so i assume you mean an ArrowChoice instance for "Kleisli m" and a Monad instance for "m"?
19:01
<nil_>
I should have figured that out on my own...
19:01
<benzrf>
Cale: doesn't even just Category (Kleisli m) give you Monad m?
19:02
<nil_>
Well, I guess that could make for a fair comparison.
19:03
<Cale>
benzrf: Not if you abstract Kleisli m away and forget how it's defined :)
19:04
<Cale>
benzrf: Category a doesn't get you some Monad instance based on a
19:05
<benzrf>
but you can write "instance Category (Kleisli m) => Monad m"
19:05
<benzrf>
it just won't work very well with the resolver
19:06
<Cale>
yeah, fair enough
19:06
<Cale>
But ArrowApply a will basically get you that a ~= Kleisli m for some m
19:06
<Cale>
for some monad m
19:08
Nomenclatura joined
19:09
<nil_>
So Monad is kind of like a special case of ArrowApply?
19:09
<Cale>
They're roughly equivalent
19:09
<Cale>
apart from the fact that they constrain types of different kinda
19:09
<nil_>
What's something Monad can do that ArrowChoice cannot?
19:16
Gurkenglas__ joined
19:25
<fProgrammer>
Quick question: I've my own data type "Node" with a generic implementation of ToJSON . I want to serialize a hashmap of type (Map Node (Set Node)) Whenever I try to do that I get a compile error: No instance for (aeson-1.0.2.1:Data.Aeson.Types.ToJSON.ToJSONKey Node) arising from a use of ‘json' Ideas?
19:28
<benzrf>
fProgrammer: well, you'll need an instance of ToJSONKey, of course
19:29
<benzrf>
fProgrammer: do you want help writing one, or?
19:29
<fProgrammer>
benzrf: hmm ToJSONKey instance, how do I write that one?
19:30
<benzrf>
https://hackage.haskell.org/package/aeson-1.1.1.0/docs/Data-Aeson-Types.html#t:ToJSONKey
19:30
<benzrf>
it looks like there are default implementations for instances of ToJSON
19:31
<fProgrammer>
benzrf: Very useful, lemme go through and report back
19:31
<benzrf>
good luck :)
19:35
<fProgrammer>
benzrf: It worked! Thanks!
19:36
<benzrf>
no problem!
19:45
<monochrom>
ToJSON doesn't buy you ToJSONKey.
19:45
<monochrom>
err, nevermind
19:48
Gurkenglas__ joined
19:55
<nil_>
Bump: What's something Monad can do that ArrowChoice cannot?
19:56
<benzrf>
nil_: that's a tricky question
19:56
<benzrf>
nil_: the "strength" issue is more like
19:56
<benzrf>
given some ArrowApply k, there is definitely an `m' (which is a monad) such that k is isomorphic to Kleisli m
19:56
<benzrf>
that's not necessarily true of an ArrowChoice in general
19:56
<benzrf>
(is my understanding of what Cale said)
19:57
<monochrom>
I don't have an example yet, but here is the idea: (>>=)'s "a -> M b" gives you unbounded choice, ArrowChoice gives you binary choice (and by induction, bounded choice).
19:57
<nil_>
monochrom: huh, that's interesting.
19:58
<nil_>
benzrf: I think I kind of see what that's supposed to mean.
19:58
<nil_>
An ArrowApply doesn't automatically give rise to an ArrowChoice though, does it?
19:59
<nil_>
So they are not like Applicative ~> Monad.
20:00
<monochrom>
Does. My lazy route: Convert ArrowApply to Monad, then see how you have "instance Monad m => ArrowChoice (Kleisli m)"
20:01
<monochrom>
But again the real idea is that ArrowApply gives you Monad, so you have unbounded choice, now just need to use it for binary choice.
20:02
<nil_>
Right, I think I got it.
20:02
<monochrom>
To a large extent, ArrowApply is telling a join-like story. But it is useful to recall that it can be converted to a >>= story.
20:03
<monochrom>
Hrm, it also looks like the morphism for exponentiation objects.
20:04
<monochrom>
(very imprecise language)
20:09
uglyfigurine joined
20:10
uglyfigurine joined
23:06
exferenceBot joined