<    March 2017    >
Su Mo Tu We Th Fr Sa  
          1  2  3  4  
 5  6  7  8  9 10 11  
12 13 14 15 16 17 18  
19 20 21 22 23 _2_4 25  
26 27 28 29 30 31
00:00 <centril> freeside: no... but you want to get started with programming in a way that lets you do something so you dont get bored
00:00 bydo joined
00:00 <freeside> in most cases, i would agree, but neophytes is a self-declared mathhead so
00:00 <centril> freeside: at least that is important to first year university students
00:00 atk joined
00:01 <centril> freeside: but not programming-head tho ;)
00:01 <freeside> as for the unboring stuff, i think web interaction and graphics programming are my top candidates for getting quick wins
00:01 <centril> Math is nice, but it is not CS
00:01 <centril> freeside: some purescript love ?
00:01 <freeside> well, we'll see what happens when he/she comes back
00:02 <centril> Cale: http://langserver.org/
00:03 <centril> Cale: https://github.com/sourcegraph/sublime-lsp
00:04 michael1 joined
00:04 fDev2179 joined
00:04 <centril> god... every time I see code written in Go I get crazy mad & sad...
00:05 <freeside> langserver looks nice, like netpbm for languages
00:05 bjz joined
00:05 <centril> Go Induces Uncontrollable Rage (TM)
00:05 <centril> freeside: =)
00:06 theDon_ joined
00:10 fDev2179 left
00:12 YongJoon joined
00:13 cads joined
00:14 jutaro joined
00:16 raycoll joined
00:17 <Cale> centril: How... how does that help me though?
00:18 <centril> Cale: not sure, but it makes text editors more like IDEs
00:18 <Cale> I don't actually want my text editor to be much like an IDE
00:18 <centril> so jumping to language definitions and stuff becomes better
00:18 <Cale> I just want it to read a file consisting of strings, filenames, and line numbers
00:18 <Cale> and be able to jump to the appropriate file when I press a button :)
00:19 brisbin_ joined
00:19 <centril> Cale: for the purposes of jumping to a function def, right ?
00:19 <c_wraith> so.. you like tag files
00:19 <freeside> i use emacs, i don't know what you all are talking about because i can't tell the difference between a text editor, an IDE, an operating system, and a tetris arcade game
00:19 <monochrom> I don't think the point is IDE. I think the point is reducing from M languages x N editors to M + N.
00:19 <centril> freeside: LOL
00:20 <Monoide> freeside: «emacs is a cool OS, just lacks a good text editor» ;)
00:20 <Cale> c_wraith: Well, yeah, my current concern was how to get Sublime Text to read tags files -- there appears to be a package for it, but I've not been able to get it to actually do the thing it's supposed to do.
00:20 <ertes> "IDE" doesn't really mean anything… if we take the abbreviation itself apart, my emacs acts pretty much like an IDE: it has most haskell stuff *integrated*, and i'm *developing* with it
00:20 <monochrom> I don't like emacs as OS because it has poor concurrency.
00:20 MrcRjs joined
00:20 <centril> monochrom: well... M + N, for behaviors that are common to IDEs
00:21 <monochrom> If not for that, I would be using emacs for everything since 20 years ago.
00:21 xplat joined
00:21 plutoniix joined
00:22 <centril> I loathe any editor that separates view and input mode
00:22 bangtree joined
00:22 FullyFunctional left
00:22 <monochrom> I even almost chose emacs as my main web browser.
00:22 plutoniix joined
00:22 <Cale> I would take something which had IDE-like behaviour, but the trouble is, all the Haskell projects I work on require custom nix shells, and have all sorts of dependencies that I don't have installed globally -- so it's fairly unlikely that any of the more advanced tools are going to work.
00:22 <freeside> oh, you just haven't done enough yak shaving in emacs
00:23 <ertes> Cale: i have nix integrated into my emacs, plus local packages (via nix)
00:23 <freeside> you are like twenty lines of ELISP away from getting exactly what you want
00:23 <ertes> Cale: my GHCi in haskell-interactive-mode is actually wrapped by nix-shell
00:23 <freeside> see? all it takes is yak shaving
00:24 <Cale> But then I have to put up with emacs
00:24 <Cale> I guess I could live with it somewhat
00:24 michael1 joined
00:24 <ertes> that's up to you of course
00:24 <freeside> right, how else were you planning to procrastinate?
00:24 <monochrom> IRC is how I plan to procrastinate. :)
00:25 <monochrom> Pretty sure that speaks for everyone too :)
00:25 <Cale> ertes: I actually don't care at all about ghci integration. Mostly I just want jump to definition.
00:25 <centril> monochrom: no, I was actually here for real stuff, but then I changed to procrastination
00:25 <ertes> Cale: ultimately it's a question of whether you want to sacrifice your pinky to a life-long relationship with an editor
00:26 <Cale> (ghci integration is going to be much more complicated)
00:26 <ertes> Cale: well, most editors have TAGS support, but h-i-m actually does better: it asks GHCi
00:26 <ertes> so it's much more precise
00:26 <Cale> ah
00:26 <Cale> It's not using one of the other things built on top of the GHC API?
00:26 <* monochrom> hugs his pinky
00:27 <ertes> Cale: nope, it uses GHCi directly
00:27 <ertes> (which i appreciate… i've heard horror stories about ghc-mod)
00:27 <jgt> I'm trying to add (MonadLogger m) to some of the type constraints in https://github.com/nakaji-dayo/yesod-job-queue. When I do that, I get this error: http://sprunge.us/MMKZ. I'm trying to fix it by writing `instance MonadLogger IO where monadLoggerLog _ _ _ = return ()`, but then I get this error: http://sprunge.us/MXgK
00:27 <jgt> anyone what how to fix this?
00:28 structuralist joined
00:28 <monochrom> ghc-mod is version-brittle. You use a newer GHC, you have to rebuild ghc-mod all over again. (Everything that uses the GHC API is this way.)
00:28 <ertes> monochrom: also about its RAM hunger
00:28 <minn> Not that it's particularly hard to write, but: is there a monadic version of takeWhile hiding somewhere in the standard library?
00:29 <Cale> Well, I have 64GB of memory for a reason ;)
00:29 <ertes> i have enough RAM, but i'd like to use it for my application =)
00:29 <freeside> somebody please help jgt, i don't know enough Yesod
00:29 <freeside> minn: google suggests https://hackage.haskell.org/package/monad-loops-0.4.3/docs/Control-Monad-Loops.html
00:29 <jgt> freeside: thank you 😌
00:29 mbw joined
00:29 <ertes> minn: you should use a stream abstraction, because monadic takeWhile will perform badly
00:29 Claudius1aximus joined
00:29 <Cale> jgt: You don't need to do that
00:29 <ertes> minn: for most monads at least
00:30 pleax joined
00:30 <jle`> jgt: without knowing too much, it sounds like you're missing a _
00:30 <Cale> jgt: Presumably your monad is an instance of MonadLoggerIO, no?
00:30 <ertes> minn: take a look at pipes for example
00:30 <ertes> @package pipes
00:30 <lambdabot> http://hackage.haskell.org/package/pipes
00:30 <Cale> jgt: You can just use the thing I mentioned before to get a plain IO action for logging and use it
00:30 <jle`> jgt: monadLoggerLog takes four arguments
00:31 <jgt> Cale: I don't think so; the compiler was asking me to add (MonadLogger m) to the type constraints for a few functions
00:31 michael1 joined
00:31 <minn> freeside: I must have missed that - thanks.
00:31 <jle`> jgt: your error comes from the fact that 'return ()' is interpreted as '\_ -> ()'
00:31 <Cale> jgt: Yeah, well, you can't use monadLoggerLog directly
00:31 <Cale> jgt: But you can do something like
00:31 <Cale> log <- askLoggerIO
00:31 <Cale> and then use log instead
00:31 <ertes> minn: note that you will most likely sacrifice laziness… again: use a stream abstraction
00:31 <Cale> (probably liftIO'ed)
00:31 <jgt> Cale: I could add another _ arg; I assumed one would be missing because `$(logInfo)` takes some thing to log
00:31 <minn> ertes: I will look into that. I'm translating some Python code that used generators to perform cycle detection on infinite graphs using iterators.
00:32 <Cale> jgt: Can you link me to the code which is trying to do logging?
00:32 <Cale> or stick it on lpaste.net?
00:32 <Cale> oops
00:32 <ertes> minn: yeah, pipes is pretty much python's generators, but on steroids
00:32 <Cale> he's gone
00:33 jgt joined
00:33 <minn> Ah, I see - there's a pipes library - neat. Thanks :)
00:33 <Cale> ertes: you know what, let's try this emacs shenanigans. What do?
00:34 <ertes> Cale: are you completely new to emacs?
00:34 <Cale> I used it for a 2 month period back in 2004
00:34 <freeside> but the coughing got so bad you had to stop
00:34 <Cale> So pretty much
00:34 <Cale> Oh, and I've used it for Agda a bit
00:34 <Cale> (but that hardly counts)
00:34 <freeside> agda is practically an emacs extension as i understand it
00:35 <jgt> jle`: actually just adding that fourth _ arg seems to have fixed it
00:35 <jgt> I'll check if logging is actually working
00:35 <freeside> dude do you even liftM
00:35 <ertes> Cale: in that case i suggest that you familiarise yourself with the basics first: dealing with files, switching between buffers, handling windows, and very importantly: using the built-in help system
00:35 <jle`> jgt: oh, that fix shouldn't actually let you log anything
00:35 <freeside> lol
00:35 <Cale> ertes: I'm going to use the mouse to do all of those things, it'll be okay
00:35 <jle`> jgt: it was just to fix the compiler error heh
00:36 <ertes> Cale: after that you can set up haskell-mode, which you should still be able to manage on your own
00:36 <jgt> jle`: Oh, yeah, I thought so
00:36 bsima left
00:36 <ertes> Cale: once you have that, i will help you with setting up haskell-interactive-mode and integrating nix
00:36 <freeside> i <3 nix
00:36 cogrendel joined
00:36 <Cale> ertes: Which version of emacs should I install?
00:36 <Cale> Does it matter?
00:36 <freeside> ALL OF THEM
00:36 <ertes> Cale: it also helps to understand the haskell override system in nixpkgs in order to add your local packages to the haskellPackages set
00:36 <ertes> Cale: the latest
00:37 <Cale> Oh, I've mostly relied on other people understanding that for me.
00:37 <jle`> jgt: some more context would be helpful :)
00:37 <freeside> i am happy with http://emacsforosx.com
00:37 path[l] joined
00:37 <ertes> Cale: well, you can use reflex-platform (i assume this is what it's mostly about), or you can use my method via package overrides
00:37 hololeap joined
00:37 <ertes> if you use the former, you should be all set
00:38 <mbw> Hello everyone. I have a question about adding type signatures to local expressions in where blocks. I know that there is -XScopedTypeVariables, which helps in this regard, i.e. lets you avoid these "could not match a with a0" errors. However, how would you type signatures here: http://lpaste.net/353472 ? This is taken from https://github.com/Gabriel439/slides/blob/master/munihac/foldmap.md .
00:38 <freeside> muahaha, the yak shaving begins
00:38 <Cale> ertes: Okay, I'll assume everything will be fine :)
00:38 <jle`> mbw: can you paste the error too?
00:38 janitor1 joined
00:38 <ertes> Cale: assuming you're using nix for package management, you can get everything from nixpkgs
00:38 <mbw> of course
00:38 <Cale> I'm only using nix for project package management, not for system packages.
00:38 <jle`> mbw: but i'm also not sure where the problem is
00:39 <ertes> Cale: nix-env -iA nixos.{emacs,emacsPackagesNg.haskell-mode}
00:39 <jle`> it looks like you typed the signatures in properly and then uncommented it
00:39 <jle`> 'where' should be one line up though
00:39 <ertes> Cale: ok
00:39 <jle`> is your question purely a syntax one?
00:39 <jle`> where tally :: i -> ...
00:39 <Cale> (I tried nixos for a couple days, it was too much work to get a desktop configuration that I liked)
00:40 lambda-11235 joined
00:40 <mbw> http://lpaste.net/353472
00:41 <mbw> I had the 'where' in the correct position. The types are the ones inferred from ghc.
00:42 <jle`> mbw: what happens when you uncomment out the type signatures?
00:42 <mbw> The problem is the Monoid constraint in 'Fold', which is hidden.
00:42 <mbw> It compiles then.
00:42 ystael joined
00:42 <mbw> Or do you mean all of them? I'll check...
00:43 <jle`> oh
00:43 <jle`> ah i didn't notice your existential data type
00:44 <mbw> Yeah, that's the problem. This is something Mr. Gonzalez came up with, actually, in order to hide the constraint from the user, if I understood correctly.
00:44 andyhuzhill joined
00:45 <mbw> It's not a big deal to drop the constraint, probably, but maybe there's some way to make it work.
00:45 <jle`> mbw: you can provide type annotations to the bindings
00:45 <lyxia> you can bind existential type variables by annotating the pattern
00:46 <jle`> combine (Fold (tallyL :: i -> m1) ...)
00:46 <jle`> and then you can use those in your type signatures
00:46 <jle`> yeah, that
00:46 <ertes> Cale: once you have haskell-mode up (if all else fails, just follow haskell-mode's official guide), ping me… the indicator is that you can load a *.hs file with syntax highlighting
00:46 <mbw> ok I'll try it.
00:46 <jle`> you can also avoid scoped type variables altogether by passing in tallyL and tallyR as arguments to tally
00:46 michael1 joined
00:46 <jle`> tally tL tR x = ...
00:46 <jle`> and then Fold (tally tallyL tallyR) ....
00:46 <jle`> that might be a little less noisy
00:46 JuanDaugherty joined
00:46 <ertes> Cale: i'll guide you through the rest, but it'll most likely be tomorrow
00:47 obadz joined
00:47 wtetzner joined
00:47 <mbw> The ScopedTypeVariables thing stems from my frequent usage of typed holes.
00:48 <jle`> mbw: so you might even want to write a standalone function combineTallies :: (Monoid m1, Monoid m2) => (i -> m1) -> (i -> m2) -> i -> (m1, m2)
00:48 <mbw> So it's just some temporary representation.
00:48 <jle`> (which is just liftA2 (,))
00:48 <freeside> indeed, it appears to underscore your reliance on typed holes.
00:48 <jle`> and something similar for combineSummarize
00:49 benjic joined
00:49 Habib joined
00:49 <jle`> this wouild be the way that doesn't rely on scoped type variables, and also doesn't require you to add type annotations/bindings to your pattern matches
00:49 <jle`> which i always thought was kind of ugly, syntactically
00:49 <mbw> freeside: Is that a bad thing?
00:49 <freeside> _
00:49 <freeside> joke
00:49 peterbecich joined
00:50 nakal_ joined
00:51 Fairy joined
00:52 peterbecich joined
00:52 <mbw> jle`: Would you have an educated guess at why the existential type is used in the definition of Fold? It seems to be more trouble than it's worth, right now. The constraint would follow from the functions working on Fold, anyway.
00:53 dbmikus joined
00:53 <mbw> I didn't even have these problems when implementing lens stuff.
00:54 <jle`> is there a blog post or article associated with this?
00:54 <jle`> tekmo usually explains these things pretty well
00:54 <jle`> one guess would be that it lets Fold have an Applicative instance i suppose
00:54 <jle`> but that's not a good guess
00:54 <ertes> mbw: you need it for the Functor instance
00:54 <jle`> oh wait it doesn't need it for an Applicative instance
00:55 <jle`> you need it for a Comonad instance
00:55 markus1189 joined
00:55 doodlehaus joined
00:55 <mbw> This all comes from here: https://github.com/Gabriel439/slides/blob/master/munihac/foldmap.md, which are slides from a talk, given here: https://www.youtube.com/watch?v=6a5Ti0r8Q2s .
00:55 peterbecich joined
00:55 markus1199 joined
00:55 <edwardk> existential type in Fold?
00:55 <edwardk> oh
00:56 <edwardk> the Moore machine Fold
00:56 <ertes> it's basically the same idea as in Coyoneda
00:56 peterbecich joined
00:56 <edwardk> data Fold a b where Fold :: (r -> b) -> (r -> a -> r) -> r -> Fold a b -- that one?
00:57 <edwardk> without 'r' being held existentially, e.g. by using
00:57 <jle`> mbw: you need the Monoid constraint for 'foldMapOf'
00:57 bno1 joined
00:57 <jle`> in the focus function
00:57 path[l] joined
00:57 <edwardk> data Fold a r where Fold :: (r -> a -> r) -> r -> Fold a r -- then we are invariant in 'r'. so you basically get no useful instances, except contravariant stuff if you flop the arg order
00:57 <mbw> data Fold i o = forall m. Monoid m => Fold (i -> m) (m -> o). I haven't worked through the whole thing yet, so I don't know yet whether these things are all related.
00:57 <edwardk> as it is, the Fold type above is isomorphic to the Moore machine tyupe
00:58 <edwardk> data Moore a b = Moore b (a -> Moore a b)
00:58 <edwardk> except, its more efficient to map over repeatedly
00:59 <edwardk> as if you fmap over the 'b' argument in Moore you have to pay for it for each 'a' you feed the result, but with Fold, you only pay once for the final 'b' you want out at the end
00:59 structuralist joined
00:59 <edwardk> mbw: that one works too. its in my folds package
01:00 <mbw> I see. Thanks, I will definitely check that out as well.
01:00 <edwardk> http://hackage.haskell.org/package/folds-0.7.1/docs/Data-Fold-M.html
01:00 <edwardk> note there i explicitly 'unpack' the monoid, but you can do it the other way just as well by using reflection earlier
01:00 <edwardk> i use reflection to pass the locally defined monoid through foldMap
01:01 wraithm joined
01:01 USBoss left
01:01 <edwardk> http://hackage.haskell.org/package/folds-0.7.1/docs/Data-Fold-L.html is the Moore style fold
01:01 <edwardk> jle`: anyways you need it for Functor, so you need it for both Comonad and Applicative ;)
01:02 <jle`> does `fmap k (Fold tally summarize) = Fold tally (k . summarize)` not work?
01:04 gcross joined
01:04 <mbw> In the meantime, thanks for these references!
01:05 <edwardk> jle`: Fold :: (r -> a -> r) -> r -> Fold a r -- would have r occurring in positive and negative position
01:05 <edwardk> you can't 'fmap' out r then
01:06 <edwardk> the existential version hides r and only operates covariantly on b, a function of r.
01:06 <edwardk> so it is a functor
01:07 danthemyth joined
01:07 peterbecich joined
01:08 meandi joined
01:09 nighty- joined
01:09 takle joined
01:09 cschneid_ joined
01:12 janitor joined
01:13 structuralist joined
01:13 vtomole joined
01:14 janitor1 joined
01:17 rkazak_ joined
01:20 ghhjjjjjjjjj joined
01:21 Stanley00 joined
01:22 sdothum joined
01:22 <centril> edwardk: Say I have: type Normalizer a = a -> Maybe a ; Which yields Nothing on "no change", Just x on normalization of the term ; And then, I have an AST where I want to apply a certain Normalizer myNorm deeply, and want to do this w/o doing case l :+: r -> case (myNorm l, myNorm r) of (Just l', Just r') -> Just $ l' :+: r' ; (Just l', Nothing) -> Just $ l' :+: r ; (Nothing, Just r') -> Just $ l :+: r';
01:22 <centril> (Nothing, Nothing) -> Nothing ; ... is there a way to do this sort of thing smoothly ?
01:23 <centril> s/case l :+: r ->/case e of l :+: r ->
01:25 <centril> doing the manual case matching becomes problematic due to combinatorial explosion when dealing with complex AST constructors...
01:27 <centril> I guess I could do like: l2 :: (a -> b -> c) -> a -> b -> Maybe a -> Maybe b -> Maybe c , and for (a -> b -> c -> d), but it is not exactly very composable and elegant...
01:28 revtintin joined
01:29 skapazzo joined
01:29 subttle joined
01:29 Fairy joined
01:30 pleax joined
01:31 <lyxia> case (myNorm l, myNorm r) of (Nothing, Nothing) -> Nothing ; (l', r') -> Just $ fromMaybe l l' :+: fromMaybe r r'
01:33 <centril> lyxia: right, how do you generalize this to N instead of 2, and preferably some way that works with lenses
01:33 <centril> :P
01:33 benjic joined
01:34 <Zemyla> Okay, so it seems that, if I'm storing a value of type c => r that it's always stored in thunk form.
01:38 cdg joined
01:40 Chef joined
01:41 <lyxia> centril: how is it supposed to work with lenseS?
01:42 <lyxia> centril: This looks like the (,) All monad.
01:43 structuralist joined
01:43 ystael joined
01:43 <lyxia> or (,) Any, as in "did normalization happen Anywhere"
01:43 <oisdk> centril how about https://gist.github.com/oisdk/92b43b63ee6aba451d5daf55af528d04
01:44 <lyxia> there you go :D
01:45 <centril> lyxia: so I write an AST, data E = L Int | V String | E :+: E | E :*: E (but with records...), derive lenses for E, then, in a normalizer, I then use a lens to apply a normalization for some lens, then do it for another, and so on and "sum" the results
01:45 <centril> that's a really vague and poor description I know
01:46 <centril> oisdk: I have some reading to do =) thanks!
01:49 <centril> lyxia: "Did normalization happen anywhere?" is exactly the right semantics
01:53 faberbrain joined
01:55 dbmikus joined
01:56 doodlehaus joined
01:57 s3mi0 joined
01:57 FreeBirdLjj joined
01:58 LordBrain joined
02:02 wtetzner joined
02:05 fragamus joined
02:08 zhikin joined
02:08 Rodya_ joined
02:08 cdg joined
02:09 gcross_ joined
02:12 andyhuzhill joined
02:16 ChongLi joined
02:16 infinity0_ joined
02:16 infinity0_ joined
02:16 michael3 joined
02:18 bjz joined
02:19 infinity0 joined
02:19 voidpi joined
02:20 jmcarthur joined
02:21 <jle`> Zemyla: yes, a value of c => a is basically a function
02:21 <jle`> Dict c -> a
02:21 infinity0 joined
02:24 infinity0 joined
02:27 infinity0 joined
02:28 path[l] joined
02:30 infinity0 joined
02:30 systemfault joined
02:31 pleax joined
02:32 fotonzade joined
02:32 louispan joined
02:32 infinity0 joined
02:34 mson joined
02:34 desku joined
02:37 harfangk joined
02:40 deepfire` joined
02:44 ystael joined
02:45 Goplat joined
02:52 hexagoxel joined
02:52 louispan joined
02:55 mizu_no_oto joined
02:57 shafox joined
03:00 hucksy_ joined
03:01 darjeeling_ joined
03:02 shafox joined
03:05 redmq joined
03:05 mtncoder joined
03:05 <redmq> what's the best resource for learning how to use ekmett's linear package effectively?
03:06 plutoniix joined
03:07 gfixler joined
03:13 <jle`> redmq: there's the ocharles tutorial from the 24 days of hackage series
03:13 <jle`> but mostly just looking at the typeclasses should help you get started
03:14 <redmq> yeah, poking at the typeclasses and things like liftU2 atm.. thanks for the ocharles reference!
03:15 <jle`> most of the package is sort of just "normal" haskell data types and typeclasses
03:15 hexagoxel joined
03:16 <jle`> `data V3 a = V3 a a a` for instance
03:16 <jle`> and it has num instances, dot products, norms, etc.
03:16 <redmq> yeah, the implementations of *^ and ^* are nice
03:21 path[l] joined
03:23 Jeanne-Kamikaze joined
03:23 kadoban joined
03:25 ystael joined
03:25 takle joined
03:26 dfeuer joined
03:28 xall joined
03:29 juhp joined
03:32 peterbecich joined
03:32 pleax joined
03:35 redmq joined
03:35 <juri_> ok, hlint is nice.
03:38 peterbecich joined
03:39 aarvar joined
03:40 _sras_ joined
03:40 <_sras_> Can Lens libraries help with transformations between records?
03:41 juhp joined
03:44 vektorweg11 joined
03:44 fabianhu joined
03:45 asivitz joined
03:51 exferenceBot joined
03:54 al-damiri joined
03:54 cschneid_ joined
03:55 faberbrain joined
03:56 hexagoxel joined
03:59 jmcarthur joined
04:00 dbmikus joined
04:06 louispan joined
04:08 grayhatter joined
04:08 <grayhatter> Varible not in scope https://gist.github.com/6f6ed719c05743bcb4f7a2002e67ba26
04:09 <grayhatter> is there some magic I'm missing to get first show to work?
04:10 danthemyth joined
04:11 FreeBirdLjj joined
04:11 <Clint> grayhatter: did you import Control.Arrow (first)?
04:11 connrs joined
04:11 <grayhatter> I did not
04:11 <grayhatter> hmmm
04:12 <grayhatter> Clint: that worked
04:12 <grayhatter> how would I know that otherwise?
04:12 <grayhatter> I found First Show here https://hackage.haskell.org/package/base-
04:12 <grayhatter> but it meantions nothing about Control Arrow
04:12 <grayhatter> unless I'm blind
04:13 <Cale> Where did you see that?
04:13 <Cale> I see instances of show for the type "First" there...
04:13 <Cale> but that's unrelated
04:13 <grayhatter> oh, then I really don't know what I'm doing
04:14 <grayhatter> I googled "first show" looking for help and got that page, and it seemed like what I was looking for
04:14 eklavya joined
04:15 <Clint> it isn't
04:15 <grayhatter> yeah, makes sense now
04:15 Rainb joined
04:16 <Cale> But how did you get the idea to use the first function in the first place?
04:16 markasoftware joined
04:16 <grayhatter> https://wiki.haskell.org/Roll_your_own_IRC_bot
04:16 <grayhatter> which has Import Control.Arrow
04:16 <grayhatter> but I dropped it somehow, and it was never needed before
04:16 <Cale> ah, yes
04:16 <Cale> Well, it's hardly used, apart from that :)
04:16 <grayhatter> and there wasn't any issue before
04:17 <grayhatter> I JUST tried adding the last part, and the last section finally added Control.Arrow
04:17 <Clint> so the answer to your question might be to use hoogle or hayoo to find out where "first" comes from then
04:17 <grayhatter> thanks Clint
04:18 <grayhatter> Clint: I tried using google (hoogle is generally worthless to me)
04:18 <grayhatter> I'll add hoogle as my 2nd stop from now on
04:18 sdothum joined
04:19 <grayhatter> ahh, 3rd result on google too... I should'nt have given up so soon -_-
04:20 dbmikus joined
04:22 Big_G joined
04:23 steeze joined
04:23 svgDelux joined
04:27 manlet joined
04:29 robotroll joined
04:30 <qmm> can somsone give me an example how i can use overloadedstrings with text?
04:30 <qmm> via lpaste please
04:33 pleax joined
04:35 darjeeling_ joined
04:36 MP2E joined
04:37 redmq joined
04:37 louispan joined
04:38 <barrucadu> qmm: It just lets you use "string literals" as text literals: http://lpaste.net/1857030866790776832
04:38 <redmq> ok, i've figured out most of what i wanted to with the `linear` package. starting to spin my wheels on something basic though: how do i extend a vector?
04:39 tripped joined
04:39 <redmq> the closest i've found to the answer seems to be "deconstruct it and then reconstruct it" as in https://hackage.haskell.org/package/linear-1.20.5/docs/src/Linear.Matrix.html#m33_to_m44
04:40 <redmq> for padding a matrix, this is rather verbose
04:40 MrcRjs joined
04:41 path[l] joined
04:41 <johnw> qmm: it means that ("Foo" :: Text) type checks
04:43 meiji11 joined
04:44 isenmann joined
04:44 cdg_ joined
04:45 mounty joined
04:47 louispan joined
04:50 pavonia joined
04:53 Wizek joined
04:54 Wizek_ joined
04:54 Argue joined
04:54 codesoup joined
05:01 dbmikus joined
05:02 louispan joined
05:03 Argue_ joined
05:04 plutoniix joined
05:08 path[l] joined
05:09 louispan joined
05:11 LuckyRawApe joined
05:16 dan_f joined
05:20 louispan joined
05:20 thunderrd_ joined
05:22 _sras_ joined
05:24 brynedwa1ds joined
05:24 raycoll joined
05:24 deepfire` joined
05:26 exferenceBot joined
05:29 Argue__ joined
05:31 Deadhand joined
05:34 pleax joined
05:34 janitor1 joined
05:35 <jle`> @tell redmq yes, that's outside of the use case of the library, kinda
05:35 <lambdabot> Consider it noted.
05:36 <jle`> @tell redmq if you can express what you want as a linear algebra operation, though, then it'll work smoothly
05:36 <lambdabot> Consider it noted.
05:37 mbuf joined
05:37 louispan joined
05:37 FreeBirdLjj joined
05:38 gcross_ joined
05:43 dbmikus joined
05:44 joneshf-laptop joined
05:44 vlatkoB joined
05:45 bjz_ joined
05:46 vlatkoB joined
05:50 pyx joined
05:51 darjeeling_ joined
05:55 Rainb joined
05:57 gcross_ joined
05:57 louispan joined
05:57 faberbrain joined
05:57 pleax joined
05:57 osa1 joined
05:57 osa1 joined
05:59 Argue_ joined
05:59 Xanather joined
06:00 hexagoxel joined
06:03 jaykru joined
06:05 uncertainty joined
06:06 jhrcek joined
06:07 dec0n joined
06:08 eklavya joined
06:08 raycoll joined
06:09 orion joined
06:11 connrs joined
06:12 danthemyth joined
06:14 moongazer joined
06:14 louispan joined
06:16 sibi joined
06:17 ali_bush joined
06:17 ali_bush joined
06:20 mda1 joined
06:21 Mortomes|Train joined
06:22 path[l] joined
06:23 Habib joined
06:23 lambda-11235 joined
06:24 dbmikus joined
06:24 andyhuzhill joined
06:25 djfo joined
06:27 danvet joined
06:30 inad922 joined
06:31 hololeap joined
06:32 <hololeap> I can't figure out how to "build" something of the type :: StateT s (ExceptT e m) a
06:33 dec0n joined
06:33 Prutheus joined
06:35 raynold joined
06:37 <hololeap> I figured out `ExceptT e (StateT s m) a`: i just use `ExceptT . StateT $ f` where f has the type :: s -> m (Either e a, s)
06:37 <pacak> > return () :: StateT Int (ExceptT e m) ()
06:37 <lambdabot> error:
06:37 <lambdabot> • No instance for (Monad m1) arising from a use of ‘return’
06:37 <lambdabot> Possible fix:
06:37 <pacak> > return () :: StateT Int (ExceptT e Identity) ()
06:37 <lambdabot> error:
06:37 <lambdabot> • No instance for (Show (StateT Int (ExceptT e0 Identity) ()))
06:37 <lambdabot> arising from a use of ‘show_M707421031500494450431539’
06:38 <Eduard_Munteanu> > runExceptT . runStateT $ do { get; return 0 }
06:38 <pacak> hololeap: What do you mean "build"?
06:38 _sg joined
06:38 MrcRjs joined
06:38 <lambdabot> error:
06:38 <lambdabot> • Couldn't match type ‘a0 -> m0 (Integer, a0)’ with ‘ExceptT e m a’
06:38 <lambdabot> Expected type: StateT a0 m0 Integer -> ExceptT e m a
06:38 <Eduard_Munteanu> > runExceptT . (`runStateT` 1) $ do { get; return 0 }
06:39 <lambdabot> error:
06:39 <lambdabot> • Ambiguous type variables ‘e0’, ‘m0’, ‘a0’, ‘a1’ arising from a use of ...
06:39 <lambdabot> prevents the constraint ‘(Show
06:40 <Eduard_Munteanu> hololeap, just write it as above, you only need to unpack/run it explicitly
06:41 <Eduard_Munteanu> :t get
06:41 <lambdabot> MonadState s m => m s
06:41 <hololeap> pacak: I'm not sure how else to explain it... how do you go from something of the form `s -> m (Either e (s, a))` to `StateT s (ExceptT e m) a`
06:42 <Eduard_Munteanu> hololeap, do you actualy have a 's -> m (Either e (s, a))'?
06:46 xplat joined
06:47 <hololeap> Eduard_Munteanu: yes
06:48 <Eduard_Munteanu> Oh well, in that case just wrap it in ExceptT and StateT. But just note that you don't have to write your monadic functions that way.
06:48 hexagoxel joined
06:50 <Eduard_Munteanu> e.g. you can simply write 'return ()' instead of 'StateT . ExceptT $ \s -> return (Right (s, ()))'
06:52 refold joined
06:52 <hololeap> Eduard_Munteanu: could you show me with this example i wrote (using the `ExceptT e (StateT s m) a` form): https://gist.github.com/hololeap/d3ba45d0d6cd0c8c6d2b43ed858aaff0
06:52 Argue__ joined
06:54 ThomasLocke joined
06:54 <hololeap> am i being needlessly expressive?
06:54 darjeeling_ joined
06:56 psmolen joined
06:56 andyhuzhill joined
06:56 meandi_2 joined
06:56 MoALTz joined
06:59 pleax joined
07:00 dbmikus joined
07:01 <jle`> i wish i could define local data types
07:01 <jle`> one-off ADT's or newtypes
07:01 <jle`> that would be nice
07:01 <jle`> yes that would be the life
07:01 <jle`> i can imagine it now ...
07:03 <Eduard_Munteanu> hololeap, you could write addLine directly in StateT s (ExceptT m)
07:03 <Eduard_Munteanu> hololeap, if you make use of liftIO
07:04 juhp joined
07:04 <Eduard_Munteanu> addLine = do { oldState <- get; liftIO $ putStr ("Current state: " ++ show oldState); ... }
07:04 dev-Zero_ joined
07:06 <hololeap> Eduard_Munteanu: and would that same method make it easy to "invert" everything so that it is of type :: StateT s (ExceptT e m) a
07:06 <hololeap> (this is just a mental exercise, nothing specific)
07:07 caumeslasal joined
07:07 <hololeap> because that is where i got stuck
07:07 athan joined
07:08 vlatkoB_ joined
07:08 <Eduard_Munteanu> hololeap, the type of that can be StateT s (ExceptT e m) a, although more generically it is something like (MonadState s m, MonadError e m, MonadIO m) => m Something
07:08 <hololeap> Eduard_Munteanu: that's cool. i will have to look more into the transformer classes
07:10 raichoo joined
07:10 rossberg joined
07:10 <Eduard_Munteanu> :t get >>= liftIO . print
07:10 <lambdabot> (MonadState a m, MonadIO m, Show a) => m ()
07:11 <hololeap> what about "running" the monad in my example. is there a more generic (or "proper") way to do it than `runAddLine = runStateT . runExceptT $ forever addLineT`
07:12 takuan joined
07:12 <Eduard_Munteanu> hololeap, that's fine, although you usually don't write runners for each monadic function, but you run the big computation somewhere in main for example
07:13 freusque joined
07:13 connrs joined
07:13 <Eduard_Munteanu> e.g. main = runExceptT . (`runStateT` 0) $ do { ... }
07:14 insitu joined
07:14 xall joined
07:15 cheater joined
07:17 <hololeap> (`f` v) is an interesting equivalent to (flip f v) :p
07:18 eklavya joined
07:19 <hololeap> so you would write the addLine function directly in that do block?
07:20 <Eduard_Munteanu> hololeap, I'd write the runStuff invocation directly, addLine can be a separate function
07:21 merijn joined
07:22 sidei joined
07:23 <hololeap> Eduard_Munteanu: thanks. i will try to refactor this example using the new info at some point
07:25 tfc joined
07:26 smwangi joined
07:26 takle joined
07:27 smwangi joined
07:28 eklavya_ joined
07:28 plutoniix joined
07:34 AleXoundOS joined
07:35 doodlehaus joined
07:37 yoneda joined
07:37 Xlaech joined
07:44 alfredo joined
07:47 Argue_ joined
07:47 grayhatter left
07:49 guiben joined
07:50 thc202 joined
07:50 kosorith joined
07:51 insitu joined
07:51 raichoo joined
07:52 govg joined
07:56 biglama joined
07:57 dbmikus joined
07:58 pikajude joined
07:58 pleax joined
07:59 faberbrain joined
07:59 hexagoxel joined
08:00 djfo left
08:01 <edwardk> centril: if you're doing it recursively and want to repeatedly apply the rewrite to a fixed point if it takes a step then rewriteOf could almost be used, but the fact that plated is going to walk into your :+ makes that awkward. you can write a one off combinator using plated to recurse, match the :+ case, and apply your normalizer in one step though
08:01 _sras_ joined
08:03 magthe joined
08:03 <_sras_> Using the Lens library, can one do transformations on similar records. Say make a new record from A with only couple of fields differing?
08:04 <jle`> you mean define a new type?
08:04 <edwardk> centril: walk f (l :+ r) = .. your logic above; walk f e = fromMaybe r (f r) where r = over plated (walk f) e
08:04 <edwardk> centril: or something like that. its a couple of line combinator that does exactly what you want
08:05 <MarcelineVQ> "<jle`> i wish i could define local data types" yus, instances too
08:07 <jle`> MarcelineVQ: local instances are possible with reflection :O
08:07 edsko joined
08:07 testx_ joined
08:07 polux joined
08:07 <MarcelineVQ> type, data, pattern, instance, all seem like useful things to be able to scope
08:07 <testx_> can someone explain this? sequenceA [(>3), (<8), even] 7
08:07 <jle`> testx_: sequenceA [f,g,h] x = [f x, g x, h x]
08:08 <jle`> it uses the Applicative instance for functions
08:09 <jle`> is there a specific question you had?
08:10 razi1 joined
08:11 <testx_> jle`: how does it typecheck
08:11 <jle`> :t sequenceA
08:11 <lambdabot> (Traversable t, Applicative f) => t (f a) -> f (t a)
08:11 <testx_> sequence doesn't take 2 arguments
08:11 <jle`> t ~ []
08:11 <jle`> f ~ (r ->)
08:11 <jle`> the Applicative instance is the instance for functions
08:12 <jle`> so you get sequenceA :: [r -> a] -> (r -> [a])
08:13 ragepandemic joined
08:14 danthemyth joined
08:15 <ertes> testx_: how many arguments does 'id' take?
08:15 <testx_> 1
08:15 <ertes> > id sin 5
08:15 <lambdabot> -0.9589242746631385
08:15 <ertes> testx_: do you see why this works?
08:16 fizruk joined
08:16 <testx_> yeah i saw it after i typed
08:16 <ertes> id :: a -> a
08:16 <ertes> now let a = Double -> Double
08:16 vtomole left
08:16 <ertes> id :: (Double -> Double) -> Double -> Double
08:16 <ertes> now read jle` explanation again
08:18 Detrumi joined
08:18 <jle`> testx_: if f, g, and h are functions, then sequenceA [f,g,h] is also a function
08:19 <jle`> just like if x y and z are Maybe, then sequence [x,y,z] is a Maybe
08:19 <jle`> if x, y, and z are 'IO a', then sequenceA [x,y,z] is IO [a]
08:19 <jle`> so if f, g, and h are functions (r -> a), then sequenceA [x,y,z] is a function r -> [a]
08:19 seveg joined
08:20 ejay joined
08:20 <jle`> would it be more helpful to read it as (sequenceA [(> 3), (< 8), even]) 7 ?
08:21 <jle`> you're applying the function that `sequenceA [(> 3), (< 8), even]` returns to the number 7
08:22 <ertes> testx_: the important thing to keep in mind is that type variables can be instantiated as function types, because haskell doesn't view functions as special for the most part
08:22 <ertes> testx_: and the other thing is this rule: for all types A, B and C the notation "A -> B -> C" is equivalent to "A -> (B -> C)"
08:22 <Xlaech> now i am confused... i thought "id sin 5" would be invalid, since function application has the strongest binding. e.g (+1) (+) 3 4 does not work. But (+1) $ (+) 3 4 does..
08:23 <ertes> Xlaech: id sin 5 = (id sin) 5 = sin 5
08:23 <jle`> Xlaech: you are correct in your assumptions about binding
08:23 <jle`> id sin 5 is parsed as (id sin) 5
08:23 <ertes> Xlaech: there are no infix operators here
08:23 <Xlaech> ah i see. Thanks :)
08:23 <ertes> (except the invisible application "operator")
08:24 castlelore joined
08:24 castlelore joined
08:24 thibaud_ joined
08:25 albertid joined
08:26 Swizec joined
08:28 Argue__ joined
08:28 ebcz joined
08:28 hdeshev joined
08:30 quchen joined
08:30 eklavya joined
08:32 tg joined
08:33 dbmikus joined
08:33 fotonzade joined
08:37 <hololeap> is there a way to embed a value into a type, for instance `data Thing a = a [a]; type TestThing = Thing 3 [Int]`
08:38 connrs joined
08:38 <hololeap> in other words make a constructor that has one of the values static
08:38 caumeslasal joined
08:38 <liste> hololeap: do you mean "data Thing a = MkThing a [a]" ?
08:39 <hololeap> liste: yeah
08:39 <hololeap> or in this case "data Thing a = Thing a [a]"
08:39 sepp2k joined
08:40 <liste> hololeap: you can have "testThing :: [Int] -> Thing Int; testThing = Thing 3"
08:40 <hololeap> nvm
08:40 <hololeap> i just realized that same thing :)
08:40 <liste> you can't pattern match it though
08:40 merijn joined
08:41 louispan joined
08:41 <hololeap> that's ok for my purposes. i forgot to think of constructors as functions
08:42 maninalift joined
08:42 sidei joined
08:42 fetter_oml joined
08:42 fbergmann joined
08:43 systadmin joined
08:45 eklavya joined
08:46 subttle joined
08:49 path[l] joined
08:49 pleax joined
08:51 path[l] joined
08:52 marfoldi joined
08:56 BartAdv joined
08:57 nmattia joined
08:58 louispan joined
08:58 Iskarlar joined
08:58 albertus1 joined
09:00 cschneid_ joined
09:00 xplat joined
09:02 ramzifu joined
09:04 <_sras_> jle`: Yes. I have a record A. I want a new record B, with most of the fields same as that of A. The new fields in B are functions of a subset of fields from A.
09:05 <jle`> yeah, lens wouldn't really help you with that
09:05 bor0 joined
09:05 <_sras_> jle`: Is there anything that can help?
09:06 <jle`> you can make B contain an A
09:06 <_sras_> jle`: Using lens?
09:06 <jle`> no, like, as an ADT
09:07 <jle`> data A = MkA { aFoo :: Int, aBar :: Double }
09:07 <jle`> er i meant backwards
09:07 <jle`> if B has fields 'foo', 'bar'
09:07 albertid joined
09:07 <jle`> and A has fields 'foo', 'bar', 'baz'
09:07 <jle`> then A could just contain a B instead
09:07 cheater joined
09:08 <jle`> instead of data A = A { aFoo :: Int, aBar :: String, aBaz :: Double } and data B = B { bFoo :: Int, bBar :: String }
09:08 <jle`> you could have data A = A { aBSTuff :: B, aBaz :: Double }
09:09 <jle`> lens is...more or less completely unrelated to this
09:09 <jle`> (by 'more or less completely' i mean 'completely')
09:09 dbmikus joined
09:09 <_sras_> jle`: Yes. What is "isomorphic" when it comes to lenses?
09:10 <_sras_> I mean, what does it mean?
09:10 kosorith joined
09:10 heurist joined
09:10 <merijn> _sras_: isomorphic in math means rough "losslessly convertible"
09:10 <jle`> in the context of Haskell, if X and Y are isomorphic, then you can write a function f :: X -> Y and g :: Y -> X
09:10 <jle`> and (f . g) = id, and (g . f) = id
09:10 <merijn> _sras_: In other words, A and B are isomorphic, if and only iff, every 'A' corresponds to a unique B, and every 'B' corresponds to a unique 'A'
09:11 Habib joined
09:11 <merijn> eh, "if and only iff" is rather redundant >.>
09:12 <jle`> if X and Y are isomorphic then Y is sort of "just another way of encoding" X, kinda
09:12 <jle`> the (X -> Y) and (Y -> X) functions are witnesses to that isomorphism
09:12 <_sras_> jle`: merijn clear. Thanks.
09:12 <jle`> re: lens, the lens library has some nice combinators for composing those witnesses
09:13 _sg joined
09:13 <jle`> if i have witnsses that X and Y are isomorphic, and witnesses that Y and Z are isomorphic, then i can also make witnesses that X and Z are isomorphic
09:13 balor joined
09:14 <_sras_> jle`: What is a "Witness"?
09:14 <jle`> the combinators and the encodings of those witnesses are all really convenient and smooth to work with so that's kinda the neat thing, and also that they integrate very well with other things in haskell
09:14 <jle`> _sras_: i explained one line above that message
09:15 <jle`> but an (X -> Y) and a (Y -> X) functions are witnesses that X and Y are isomorphic
09:15 inad922 joined
09:15 <jle`> like, i know that X and Y are isomorphic if i have functions that can convert between them
09:15 <_sras_> You said. those functions are witnesses. But I don't get what you mean by that.
09:15 <Zemyla> jle`: What if f . g = id, and f . g . f = f (which is weaker than g . f = id)
09:15 bjz joined
09:15 <merijn> _sras_: Side note: that definition does not disallow/rule out multiple isomorphisms between a pair 'A' and 'B', for example if I pick 'Integer' and 'Rational' I can define an isomorphism '(/4) :: Integer -> Rational' & '(*4) :: Rational -> Integer', but the same with (/2) and (*2) is obviously just as valid
09:15 <jle`> _sras_: you can think of that as me defining a vocabulary word
09:16 <jle`> that's what i'm defining "witness" to be
09:16 <merijn> _sras_: 'witness' roughly means 'proof'
09:16 <Zemyla> Kind of like read and show, except without errors, I'm thinking?
09:16 <_sras_> Oh. Alright.
09:16 <jle`> i could use another word, floopything, maybe
09:16 <jle`> if X and Y are isomorphic, then (X -> Y) and (Y -> X)'s are the floopythings associated with that isomorphism
09:16 <_sras_> jle`: :)
09:17 <jle`> and lens is a library that lets you manipulate and encode and work with the floopythings very easily :)
09:17 <Athas> centril: regarding your Idris and Agda comment tonight, even System F type inference is exponential.
09:18 Argue_ joined
09:19 takle joined
09:20 ThomasLocke_ joined
09:20 obadz joined
09:20 mmn80 joined
09:21 augur joined
09:21 ramzifu joined
09:22 kritzcreek_ joined
09:23 maninalift joined
09:24 cluzz joined
09:24 louispan joined
09:27 tomphp joined
09:28 subttle joined
09:32 Swizec_ joined
09:34 laudiacay joined
09:34 <Habib> How would I simplify this minor monstrosity of an action?: http://lpaste.net/9152924913818927104
09:35 janitor1 joined
09:35 <merijn> Habib: Needs more where-clauses
09:36 <jle`> you can float out the return, too
09:36 <merijn> Habib: Also, what's the type of those things, since the 'maybe' and fromMaybe seems redundant
09:37 <Eduard_Munteanu> Habib, mRefererUrl <- header "Referer"; forM mRefererUrl $ \refererUrl -> do ...
09:37 sidei joined
09:38 <Habib> header "HeaderName" returns an ActionM (Maybe Data.Text,Lazy)
09:38 <Eduard_Munteanu> And if you have lots of maybes to chain you might just need MaybeT or the Maybe monad
09:38 <Habib> parseURI returns a Maybe URI
09:38 <jle`> yeah it looks like you never even use nullURI ?
09:38 Fairy joined
09:38 <Habib> I use nullURI to ensure I get a straight Bool for the if statement
09:38 <merijn> Habib: Right, so why don't use the Monad instance of Maybe?
09:38 <jle`> at least for refererUrl
09:38 <Habib> Monad instance sounds like a good idea.
09:38 fbergmann joined
09:38 qqwy joined
09:39 <qqwy> @src gcd
09:39 <lambdabot> gcd 0 0 = error "Prelude.gcd: gcd 0 0 is undefined"
09:39 <lambdabot> gcd x y = gcd' (abs x) (abs y)
09:39 <lambdabot> where gcd' a 0 = a
09:39 <lambdabot> gcd' a b = gcd' b (a `rem` b)
09:39 <jle`> Habib: btw, f <$> g <$> x = (f . g) <$> x
09:39 mohsen_ joined
09:39 <Habib> ha, yeah, that makes sense.
09:40 <qqwy> Wow, when was the extra clause for gcd 0 0 added? :o
09:40 emmflo joined
09:40 pleax joined
09:40 <jle`> so you might be able to simplify your forMaybe stuff easier
09:40 <qqwy> I distinctly remember sutumbling about the wrong result of `gcd 0 0' in the past
09:40 <qqwy> stumbling*
09:40 <jle`> using 'return' for 'Just' is also kind of confusing
09:40 <qqwy> Also: Good morning everyone :-)
09:40 <jle`> morning :)
09:40 <Habib> The return is to wrap it in an ActionM
09:40 <jle`> but is it, though?
09:41 <jle`> on lines 15, 16?
09:41 <jle`> it looks like return is 'Just' there
09:41 <Habib> Yeah, my bad.
09:41 <lpaste_> merijn annotated “sameHostReferer” with “sameHostReferer initial simplification” at http://lpaste.net/9152924913818927104#a353477
09:41 <Habib> Thought you were talking about the last lines.
09:41 <merijn> Habib: See that one
09:41 <merijn> Not 100% it typechecks, but you get the idea
09:42 <_sras_> Is there anyway to make Ghci stop output at the first error?
09:42 <Habib> Thanks, merijn.
09:44 <jle`> `f <$> Just x` is just `Just (f x)`
09:44 jutaro joined
09:46 dbmikus joined
09:47 <Habib> `return $ Just . fromString . uriPath $ refererUrl` vs `return $ fromString <$> (Just $ uriPath refererUrl)`
09:47 <jle`> return $ Just (fromString (uriPath refererUrl))
09:47 <Habib> Ugh, brackets.
09:47 <jle`> you can float up thje return too
09:47 <merijn> I would leave the $ before referrerUrl, but remove the $ after return
09:48 <jle`> and just do Just (fromString (uriPath renderUrl))
09:48 <Habib> What do you mean by float up? Are you referring to wrapping the whole if statement in a return and removing the two returns?
09:48 <merijn> i.e. 'return . Just . fromString . uriPath $ refererUrl'
09:48 <jle`> or Just $ fromString (uriPath renderUrl) if you're averse to brackets
09:48 <jle`> yes
09:48 <jle`> `if x then f y else f g` is the same as f (if x then y else g)
09:49 <jle`> s/g/z
09:49 <jle`> you can also use guard if that's your fancy
09:50 <jle`> if p then Just y else Nothing => Just y <* guard p
09:50 jabbslad_ joined
09:50 <Habib> I like your idea of floating the return, but it kind of messes with the indentation a little http://lpaste.net/9152924913818927104
09:51 <jle`> you do need to indent the then/else, yes
09:51 <merijn> Habib: That's solved my fixing your indentation to be less awful ;)
09:51 cdg joined
09:51 <Habib> Haha, it's true, current indentation is bad, anyway.
09:52 <jle`> i'd name the Bool something nice in a let statement
09:52 <Habib> mixing lets and wheres.
09:52 <jle`> it's a let inside a do block
09:52 <jle`> it's pretty common
09:52 <lpaste_> merijn annotated “sameHostReferer” with “sameHostReferer simplification round two (annotation)” at http://lpaste.net/9152924913818927104#a353478
09:52 <merijn> That's not perfect, but already better
09:53 <jle`> let's inside do block are different than let .. in ..'s
09:53 <jle`> and then you can do Just (fromString (uriPath refererUrl)) <* guard isValid
09:53 <merijn> jle`: I hear people say that, but I don't really see in what way they're diffrent, except for, like a tiny irrelevant syntactic detail?
09:54 Fairy joined
09:54 <Habib> I think that's the best we'll get for now. I hate that refererUrl /= nullURI, as it's essentially a null check that's only there because of the fact that we had to extract the values from their Maybes.
09:54 cdg joined
09:54 <Habib> It's a sentinel value check.
09:54 <jle`> by 'different' there i meant different in that the hueirstics apply differently
09:54 nilof joined
09:54 <jle`> Habib: you can get rid of that by just using forM, as mentioned earlier
09:55 <Habib> Ah, I missed that, let me go back.
09:55 <merijn> Habib: Well, you could also handle this by removing the "maybeURI" for referrer and handling this in an explicit case
09:56 <Habib> I thought about a case statement when I was initially deciding between case or if, but I figured it wouldn't work (when I looked at the ZVON example).
09:57 <jle`> if you get refererUrl before the 'fromMaybe'
09:57 subttle joined
09:57 <jle`> you can forM :: Maybe a -> (a -> IO b) -> Maybe b
09:57 <jle`> that is, if refererUrl is Nothing, then just short-circuit and return Nothing
09:57 <jle`> otherwise do stuff on the insides
09:58 <jle`> oh but hm, that way you wouldn't be able to return a Nothing further inside
09:58 <Habib> But wouldn't the signature have to be something like forM :: Maybe a -> (a -> IO b) -> IO (Maybe b)?
09:58 <jle`> yes, you're right, that's a typo on my part
09:59 <jle`> but it might not fit perfectly in this situation because you want to be able to further Nothing it all inside the (a -> IO b)
09:59 <jle`> so explicit case matching is probably the better way. unless you want to go all the way and use MaybeT
10:00 blackbear joined
10:01 faberbrain joined
10:01 <Habib> https://www.youtube.com/watch?v=T-sxSd1uwoU&t=1m17s
10:02 <lpaste_> jle` annotated “sameHostReferer” with “sameHostReferer simplification round two (MaybeT)” at http://lpaste.net/9152924913818927104#a353480
10:02 <jle`> the whole thing actually kinda cleans up nicely w/ MaybeT
10:02 <jle`> fsvo nicely
10:02 <jle`> because then the guard can go in as a normal MaybeT action
10:03 pleax joined
10:03 pmikkelsen joined
10:03 <Habib> I've never understood the SomethingT convention (how it works, anyway).
10:03 <jle`> and fromMaybe for the host header was always just a perverted version of <|> anyway
10:03 <Habib> I need to understand MaybeT first
10:04 <jle`> Habib: are you familiar with newtype wrappers to give things different instances?
10:04 <Habib> Yes.
10:04 <Habib> But not intimately.
10:04 <jle`> like how we can use the 'Sum' newtype wrapper to give Int its own Monoid instance that is addition
10:04 <jle`> > Sum 10 <> Sum 11
10:04 <lambdabot> Sum {getSum = 21}
10:04 <Habib> I don't use newtype, really.
10:04 <jle`> > Product 10 <> Product 11
10:04 <lambdabot> Product {getProduct = 110}
10:04 stef204 joined
10:04 <jle`> by adding a newtype wrapper, we can give things different and sometimes more useful typeclass instances
10:04 <Habib> Yes, I understand all that, but I don't use newtype, so I may be rusty.
10:04 <hydraz> newtype is good
10:05 <jle`> MaybeT is a newtype wrapper that gives us a useful instance in this case
10:05 subttle joined
10:05 qqwy joined
10:05 <jle`> it's a 'MaybeT Action a' is a newtype wrapper over 'Action (Maybe a)' that gives us a useful Monad and Alternative instance
10:05 <jle`> namely, that >>= respects the Maybeness of everything
10:05 marr joined
10:06 <jle`> 'guard' is a short-circuit Nothinger
10:06 <jle`> and <|> is "error recovery"
10:06 <Habib> Huh, but isn't ActionM just type ActionM = Web.Scotty.Internal.Types.ActionT Data.Text.Internal.Lazy.Text IO
10:06 <jle`> maybe, but that isn't too relevant here
10:06 <jle`> all we really wanted to do was build an ActionM (Maybe referrer)
10:07 <jle`> and MaybeT is a way to build one nicely
10:07 <Habib> Okay, I see; I'm just trying to understand what the T convention stands for.
10:07 <jle`> ah, the T usually means monad transformer
10:07 <jle`> but you don't need to understand monad transformers to use MaybeT as it applies here
10:07 <Habib> Ah, okay.
10:08 <jle`> basically, normally, for IO, (>>=) :: IO a -> (a -> IO b) -> IO b
10:08 esad joined
10:08 <Habib> I think I vaguely understand monad transformers. They transform monads so that you can work across monads, right?
10:08 worch joined
10:08 <jle`> MaybeT lets us have a much more interesting instance, (>>=) :: IO (Maybe a) -> (a -> IO (Maybe b)) -> IO (Maybe b)
10:08 <jle`> it lets you have a (>>=) that "respects" nothingness
10:08 <jle`> and lets you short-circuit your IO actions
10:09 pmikkelsen left
10:09 <Habib> Okay, and where does `guard` get imported from?
10:09 <jle`> Control.Applicative i think? or Control.Monad
10:09 qqwy` joined
10:10 <jle`> guard is "fail here and return Nothing right away if the predicate is False"
10:10 <hydraz> Applicative.
10:11 <Habib> Yep, I see. BTW, Hoogle says Control.Monad.
10:13 <jle`> with `MaybeT Action a`, you're basically working with `Action (Maybe a)`s, except you get nice combinators like <|> and guard and a new '>>='
10:13 <ezyang> Do people think that http://hs01.scs.stanford.edu:8000/dist/doc/html/str-sig/Str.html should have a more clear marking saying that this is a signature?
10:13 <jle`> (<|>) :: Action (Maybe a) -> Action (Maybe a) -> Action (Maybe a), now. guard :: Bool -> Action (Maybe a) (with the newtype wrapper unwrapped)
10:13 <ezyang> If so, where should it be? Str (Signature) in the title?
10:15 sidei joined
10:15 danthemyth joined
10:15 ChewieBeardy joined
10:17 FreeBirdLjj joined
10:17 request_error left
10:18 s4msung joined
10:18 MrcRjs joined
10:20 seveg_ joined
10:21 <lpaste_> ChewieBeardy pasted “Evalexpr on QuickCheck” at http://lpaste.net/353481
10:21 <ChewieBeardy> oh wow, didn't have the time to ask my question :P
10:21 <ChewieBeardy> that bot is quicker than me
10:22 <ChewieBeardy> anyway, hi guys :D I'm trying to play with QuickCheck, and I was thinking of verifying a simple evalexpr program
10:22 <merijn> ChewieBeardy: Right, that property is not really sensible
10:22 dbmikus joined
10:22 <ChewieBeardy> yeah, as soon as I thought about building up the arbitrary definition, I realized I'd need to "build up" the associated n along with it, which essentialy was recoding the eval function
10:22 <Habib> jle I'm curious, how does guard short-circuit for IO? I can see how it would do it for Maybe, just give back Nothing (which is empty for Alternative Maybe) and all further binds are ineffectual. But what IO action exists where further binds are ineffectual?
10:23 <ezyang> raises an exception
10:23 <Habib> Ah, that makes sense.
10:23 <jle`> Habib: for IO it raises an exception yes
10:23 <ezyang> >> mfail :: IO ()
10:23 <merijn> ChewieBeardy: For property based testing (like QuickCheck) you wanna think along the lines of: "prop_add_commutative :: Expr -> Expr -> Bool; prop_add_commutative e1 e2 = eval (Add e1 e2) == eval (Add e2 e1)"
10:23 <ezyang> > mfail :: IO ()
10:23 <lambdabot> error:
10:23 <lambdabot> • Variable not in scope: mfail :: IO ()
10:23 <lambdabot> • Perhaps you meant ‘fail’ (imported from Control.Monad.Writer)
10:23 <jle`> but for `MaybeT IO`, it returns Nothing
10:23 <ezyang> > guard False (return ()) :: IO ()
10:23 <Habib> Understood.
10:23 <lambdabot> error:
10:23 <lambdabot> • Couldn't match type ‘()’ with ‘IO ()’
10:23 <lambdabot> Expected type: m0 () -> IO ()
10:24 <ezyang> > guard False :: IO ()
10:24 <merijn> ChewieBeardy: Naah, don't think along lines of "generate associated 'n'', think along lines of "what properties can I state about just expressions?
10:24 <lambdabot> <IO ()>
10:24 <ezyang> sigh :)
10:24 <merijn> i.e., like the commutativity of Add I just gave
10:24 <ChewieBeardy> hm I see
10:24 <jle`> the behavior of 'guard' is meant to be interpreted alongside the behavior of (>>=) (and (<|>))
10:24 <ChewieBeardy> so properties of the structure, but not properties of the "reduction" of the structure into a value
10:24 <merijn> ChewieBeardy: Or how about "sub_prop e1 e2 = eval (Sub e1 e2) == eval e1 - eval e2"?
10:24 phaji joined
10:25 <jle`> ezyang: do you mean a signature as opposed to an empty data decl?
10:25 dev-Zero_ joined
10:25 <ChewieBeardy> those are good ideas, thanks merijn
10:25 <merijn> ChewieBeardy: "equal_sub e = eval (Sub e e) == 0", endless options :)
10:26 <ezyang> jle`: I mean signature
10:26 <ChewieBeardy> so a rule of thumb would be to have properties where the structure exists on both sides
10:26 <ezyang> as in, Backpack signature
10:26 <ezyang> (taking down server briefly)
10:26 <merijn> ChewieBeardy: I just ruined your rule of thumb with that last suggestion ;)\
10:26 <ChewieBeardy> indeed :P
10:26 <jle`> yeah, i would normally interpret that an opaque data type if i read it now
10:27 Swizec joined
10:27 <ChewieBeardy> so, would a "leaf case" property like prop_value e@(Value n) n = eval e == n make sense?
10:27 <ezyang> new link is http://hs01.scs.stanford.edu:8000/str-sig/dist/doc/html/str-sig/Str.html
10:27 <ezyang> jle`: Sorry, I'm not talking about the Str type; I'm talking about the model header up top
10:27 <ezyang> *module
10:27 <merijn> ChewieBeardy: Well, that's not a valid definition, but "prop_value :: Int -> Bool; prop_value n = eval (Value n) == n" would be reasonable
10:27 raichoo joined
10:28 psychicist__ joined
10:28 <merijn> ChewieBeardy: Mainly you just wanna avoid your properties relying on complex relations between your input arguments, like your original example did
10:28 <merijn> ChewieBeardy: As you can see, if you start thinking about the rules of expressions you can probably think of a dozen properties based on my suggestions for all of those :)
10:29 <ChewieBeardy> yeah, you opened up a whole world for me :D
10:29 <ChewieBeardy> thank you so much
10:29 <ChewieBeardy> I'm trying to build up a small workshop for colleagues who want to discover functional programming, me included, so this kind of stuff is gonna work wonders
10:32 cdg_ joined
10:33 Argue__ joined
10:38 Gurkenglas_ joined
10:39 jaspervdj joined
10:42 Rodya_ joined
10:43 netheranthem joined
10:43 ph88_ joined
10:44 skapazzo joined
10:44 _ashbreeze_ joined
10:45 oisdk joined
10:45 hexagoxel joined
10:45 Mortomes|Work joined
10:46 Guest92877 joined
10:49 subttle joined
10:52 arcanine joined
10:52 louispan joined
10:52 balor joined
10:53 raichoo joined
10:53 kosorith joined
10:54 sword865 joined
10:56 silver joined
10:59 dbmikus joined
10:59 systadmin joined
11:01 nyuszika7h1 joined
11:02 Snircle joined
11:02 faberbrain joined
11:05 teshe joined
11:06 tjbp joined
11:06 <teshe> hello who is online here
11:06 seveg joined
11:07 soLucien joined
11:08 tjbp joined
11:08 danthemyth joined
11:08 <ph88_> you and 1472 others
11:09 petermw joined
11:11 teshe left
11:11 <ongy> now it's just 1472 others
11:11 tjbp joined
11:12 beerdrop joined
11:14 unK_ joined
11:15 bhavya joined
11:15 mizu_no_oto joined
11:16 maninalift joined
11:16 stoopkid joined
11:17 petermw joined
11:21 xall joined
11:21 cic joined
11:21 tomboy64 joined
11:22 <tomboy64> i'm trying to wrap my head around applicative functors, but don't get why https://paste.pound-python.org/show/GiFHYiid1EOlrrwvaBkP/ doesn't work
11:22 <tomboy64> could someone enlighten me?
11:24 <suppi> tomboy64: why are you using <$>?
11:24 uncertainty joined
11:24 <tomboy64> because i am working under the assumption that t will be an IO String?
11:25 <tomboy64> is that wrong?
11:25 <srhb> tomboy64: getLine is IO String, t is String
11:25 <tomboy64> doh
11:26 <suppi> t <- getLine; f t is syntactic sugar for getLine >>= \t -> f t
11:26 <suppi> check the type of >>= :)
11:26 Habib left
11:27 <tomboy64> yes
11:27 <tomboy64> ugh
11:28 Cooler joined
11:28 <Cooler> is this ide real? http://simonmar.github.io/bib/papers/vshaskell.pdf
11:28 <suppi> you can do: result <- doubleIt <$> getLine :)
11:28 <Cooler> they don't give a download link
11:29 caumeslasal joined
11:30 Fairy joined
11:30 <suppi> which year is this from? emacs does a lot better than that :)
11:30 bennofs joined
11:30 <tomboy64> thanks. it's beginning to clear up a little.
11:32 eatman joined
11:32 eatman joined
11:33 <suppi> note that <$> is fmap
11:33 <tomboy64> yes, that i know
11:34 <tomboy64> and i also get the notion it pushes a function into a monad and applies its value
11:34 unK_ joined
11:35 <tabaqui1> #join archlinux
11:35 <tabaqui1> oups
11:35 <tabaqui1> sorry
11:35 dbmikus joined
11:35 janitor joined
11:37 mniip joined
11:37 doodlehaus joined
11:39 fbergmann joined
11:41 whaletechno joined
11:43 janitor1 joined
11:45 Rodya_ joined
11:45 JeanCarloMachado joined
11:46 yellowj joined
11:46 HoierM joined
11:48 <_sras_> Is there a function in lens library that accept a template haskell's Dec, representing a Data type definition, instead of a Name and make lenses for it?
11:48 doodlehaus joined
11:50 <lyxia> _sras_: _DataD
11:53 <_sras_> lyxia: Didn't get you.
11:53 desktop joined
11:53 CoolerExtreme joined
11:53 <lpaste_> Vzox01 pasted “Can I do anything with Constrs?” at http://lpaste.net/353484
11:53 asthasr joined
11:54 <Vzox01> Hello, everyone! I'm having a problem with understanding whether I can achieve something with syb and Data.Data, I
11:54 <Vzox01> I've posted my question here: http://lpaste.net/353484
11:54 amoe_ joined
11:55 <ertes> is suppose there is no way to make GHCi support *.hsc files?
11:55 <ertes> i need to use a bunch of linux APIs, and it would be nice, if i could hack that support interactively
11:55 tsdh joined
11:56 unenforcer joined
11:57 <merijn> ertes: You can make ghci load object code (I forget how), but that doesn't solve the issue of needing to compile before loading into ghci
11:57 cpennington joined
11:58 <ertes> i wouldn't mind compiling
11:58 <lyxia> _sras_: Sorry I totally misunderstood you.
11:58 <merijn> ertes: Then consult the GHC manual on how to make ghci load object code
11:58 pleax joined
11:59 dramforever joined
11:59 <_sras_> lyxia: It is alright. I got the answer.
12:00 <_sras_> lyxia: declareLensesWith :: LensRules -> DecsQ -> DecsQ, was what I was after, I think so.
12:00 Rodenbach joined
12:00 <ertes> merijn: actually that sounds like a good idea… GHCi will load *.o automatically, if it's newer than the corresponding source file
12:00 <lyxia> _sras_: right
12:02 slomo joined
12:02 slomo joined
12:02 sdothum joined
12:04 lukaramu joined
12:05 max3 joined
12:06 <lyxia> Vzox01: you can use fromConstrM with State
12:07 coot joined
12:07 <lyxia> Vzox01: Have you considered GHC.Generics instead though
12:07 <lyxia> It's much safer.
12:08 <Vzox01> lyxia: no, I don't know anything about Generic programming :) just learning
12:09 <lyxia> Vzox01: GHC.Generics is the modern approach to generic programming in Haskell.
12:10 <Vzox01> lyxia: alright, I'll research it, thank you! the only other library that I tried was uniplate, but I couldn't find a way to do what I wanted with it
12:11 asmyers joined
12:11 sidei joined
12:11 dbmikus joined
12:12 nomicflux joined
12:12 <lyxia> Vzox01: the documentation contains a short tutorial http://hackage.haskell.org/package/base-
12:12 maninalift joined
12:13 rcat joined
12:14 rekahsoft joined
12:14 Swizec joined
12:15 <tomboy64> suppi, could you help me again? my original intention was to a) get an input (number) which triggers (number) loops of requesting multiple (n) lines of input, which then again should be shoved into a function f to be processed.
12:15 <tomboy64> so, using >>= can i chain getLine somehow n times to apply to a function f?
12:17 oish joined
12:17 doodlehaus joined
12:17 <suppi> not entirely sure i understood that. if you could write a type signature for that it would help :)
12:18 <ongy> tomboy64: you may be interested in replicateM
12:18 jutaro joined
12:18 <tomboy64> f :: String -> String -> String -> Int
12:18 danthemyth joined
12:19 <tomboy64> with the strings coming from 3 getLine calls
12:19 <tomboy64> ongy: looking at it
12:19 <dramforever> tomboy64: is '3' from input or constatnt (known in advance)?
12:20 <Rembane> tomboy64: Have you checked out repeatM?
12:20 <ongy> tomboy64: you can do [String] -> Int, 'String -> String -> String -> Int' states that you need 3 lines already, so why would ask for the linecount befor that?
12:20 <tomboy64> 3 is constant
12:20 <Rembane> :t repeatM
12:20 <lambdabot> error:
12:20 <lambdabot> • Variable not in scope: repeatM
12:20 <lambdabot> • Perhaps you meant one of these:
12:20 <Rembane> Bah
12:20 <Rembane> :t replicateM
12:20 <lambdabot> Applicative m => Int -> m a -> m [a]
12:20 <Rembane> tomboy64: I meant replicateM
12:21 <tomboy64> ongy: i'm not asking for the linecount before, i'm asking for the repetition of the whole thing, n*(3 linecounts+stdouts)
12:21 <ongy> oh, so you want to read n*3 lines after that?
12:21 <tomboy64> replicateM seems to do what i want. now lets experiment.
12:21 <tomboy64> ongy: correct
12:21 <dramforever> f :: String -> String -> String -> Int
12:21 louispan joined
12:22 <ongy> ah, that still works fine with replicateM, you can put the entirety of getting the 3 lines and then running your function into the argument if you want to
12:22 <Rembane> For instance: (read <$> getLine) >>= \n -> replicateM n getLine >>= f
12:22 noteshui joined
12:22 <dramforever> Note: Using replicateM loses information, that the function is called with 3 String's
12:23 <dramforever> :t let f = undefined :: String -> String -> String -> Int in liftA3 f getLine getLine getLine
12:23 <lambdabot> IO Int
12:23 <dramforever> liftA3 f getLine getLine getLine -- This is what I would recommend
12:24 <quchen> bitonic: After knowing your nick for umm years, I just found out who you are. And that’s why I always write my nick on my name badges at conferences haha
12:24 <merijn> quchen: See, I'm easy to spot at conferences! :p
12:24 <merijn> If your nick is your name, there's never any confusion! (Until you have multiple people with the same name...)
12:24 <quchen> merijn: I haven’t spotted you on any yet
12:25 <merijn> In which cases the David's are a bit overrepresented, I guess :p
12:25 xall joined
12:25 <tomboy64> dramforever: hehehe something new to read up about... never got into contact with lift before
12:25 <merijn> quchen: I hope to sucker my supervisor into paying for ICFP this year :p
12:25 <tomboy64> thanks so far, folks
12:25 <dramforever> tomboy64: It's an Applicative thingy
12:25 <dramforever> :t liftA3
12:25 <lambdabot> Applicative f => (a -> b -> c -> d) -> f a -> f b -> f c -> f d
12:26 oish_ joined
12:26 <dramforever> It's like f <$> getLine <*> getLine <*> getLine
12:26 <dramforever> but pre-packaged into one function
12:26 <ongy> merijn: merijn is your name?
12:26 <merijn> ongy: Yeah
12:26 <tomboy64> which is what my original plan was. your latter line.
12:26 <ongy> I wonder if people would notice who I am...
12:26 <quchen> My name is »quchen«, but my passport lists another name.
12:26 TheEpsylon joined
12:27 <quchen> (That name is also my name, it’s not like I’m trying to hide it. But when people talk about cake in German it’s awkward.)
12:27 fotonzade joined
12:28 <ongy> quchen: remind me to bring you some Kuchen if I ever meet you
12:28 FullyFunctional joined
12:28 <quchen> I will! How do I recognize you? :-D
12:28 whaletechno joined
12:29 <lyxia> Vzox01: BTW to get Add :: Int -> Command from its constr (= toConstr (Add undefined)): \n -> fromConstrB (fromJust (cast n)) constr. The cast is safer than fromConstr . toConstr.
12:30 <lyxia> Vzox01: it becomes fairly annoying if your constructor has more fields.
12:30 pleax joined
12:31 cyborg-one joined
12:32 lep-delete joined
12:32 <tomboy64> for later use: is there an easy way to make replicateM strict? e.g., make sure it only continues processing my program when all results are collected?
12:32 ramzifu joined
12:32 <dramforever> tomboy64: The e.g. part: yes it does
12:33 <dramforever> it's exactly like you said
12:33 <tomboy64> nice, thanks!
12:34 jhrcek joined
12:34 <ongy> quchen: search for people that have ongy in their name :)
12:36 lithie joined
12:36 <bitonic> quchen: aha, I did tell you who I am a couple of times though
12:36 <quchen> ongy: ZuriHac is my next Haskell conference :-)
12:36 <bitonic> But I guess a badge is better
12:37 <quchen> bitonic: You did? Ohhhh
12:37 <bitonic> quchen: I think so yeah
12:37 <bitonic> See you at ZuriHac BTW
12:37 <quchen> I’ll show myself out then, in shame :-)
12:37 <quchen> Yeah!
12:37 oish joined
12:37 <bitonic> Apparently there will be like 300 people lol
12:38 <bitonic> Although no sausage and beer for breakfast
12:38 <_sras_> What does the `declareLensesWith` function of the lens library include the Record dec passed in as its argument in the output? How to make it stop doing that?
12:38 <_sras_> s/What/Why
12:38 maninalift joined
12:38 <quchen> bitonic: Käsefondue for breakfast!
12:38 <bitonic> That would be hardcore lol
12:39 fragamus joined
12:39 <quchen> I don’t think Haskell’s type system is strong enough to catch all the bugs a horde of whining full-of-cheese programmers would produce during the day
12:39 <bitonic> Cheese mixed with alcohol
12:40 insitu joined
12:40 <quchen> Not much though. I dare you to get drunk from Käsefondue.
12:40 systadmin joined
12:41 pleax joined
12:42 Argue_ joined
12:44 danthemyth joined
12:46 Rodya_ joined
12:46 <tdammers> Haskell's type system is strong enough to require a horde of cheese-laden programmers in order to make serious bugs though
12:46 <ongy> it's not hard to make bugs
12:47 <tdammers> well, that was obviously tongue-in-cheek
12:47 <ongy> how many functions are completly defined by their type alone? 'id :: a -> a' I think, anything else?
12:47 <quchen> ongy: Lots!
12:48 <quchen> :t uncurry
12:48 <quchen> :t curry
12:48 <lambdabot> (a -> b -> c) -> (a, b) -> c
12:48 <lambdabot> ((a, b) -> c) -> a -> b -> c
12:48 <quchen> :t const
12:48 <tdammers> fmap
12:48 <lambdabot> a -> b -> a
12:48 <tdammers> (almost)
12:48 dbmikus joined
12:48 <quchen> The Functor laws are not in fmap, but they’re critically important, so I don’t think that one counts
12:48 <quchen> I think >>= for Cont is also unique
12:49 <ongy> oh, right there's a lot
12:49 <tdammers> anyway, the grain of truth I was hinting at is that maneuvring yourself into a situation where it's easy to accidentally introduce bugs and not notice them until they're in production is rather difficult in Haskell
12:49 <ongy> oh suddenly there's and accidentally :)
12:49 <quchen> ((a -> r) -> r) -> (a -> (b -> r) -> r) -> (b -> r) -> r
12:49 <tdammers> :)
12:49 <quchen> That should be it :-)
12:49 <tdammers> yes
12:49 <tdammers> that's the "tongue-in-cheek" part
12:49 descender joined
12:51 <ongy> continuation monad is great
12:52 emc2 joined
12:52 <quchen> <*> for Reader is unique (= the S combinator)
12:52 <quchen> So is K
12:52 <quchen> s f g x = f x (g x)
12:52 <quchen> k x y = x
12:52 <quchen> :t \f g x -> f x (g x)
12:53 <lambdabot> (t2 -> t -> t1) -> (t2 -> t) -> t2 -> t1
12:53 <quchen> :t \x y -> x
12:53 <lambdabot> t -> t1 -> t
12:53 jutaro joined
12:54 <quchen> I’m not sure how to prove that a type has a unique implementation though. (Neither in Haskell-without-⊥ nor in stronger/other type systems.)
12:54 asthasr joined
12:54 systadmin joined
12:56 Acer joined
12:56 <Acer> anyone have the haskell programming from first principles book?
12:57 <ongy> when I wanted to make a monad instance that wraps callbacks, I wanted to look up the Continuation monad instance, but I kind of failed doing that, I only found a bunch of transformers, but couldn't really find the source for those either :(
12:58 <quchen> ongy: http://www.haskellforall.com/2014/04/how-continuation-monad-works.html
12:58 c0ncise joined
12:59 danza joined
13:00 Achylles joined
13:00 <Acer> need help with the state monad chapter of that book
13:00 <Acer> how does this work, intToDie <$> state (randomR (1, 6))
13:00 <quchen> <$> is fmap.
13:01 <quchen> So this is equivalent to »do { foo <- state (randomR (1,6)); pure (intToDie foo) }«.
13:01 <quchen> (pure = return, if you’re wondering.)
13:01 juhp joined
13:01 albertid joined
13:01 <ongy> quchen: my problem wasn't understanding it, I just didn't find the code I was searching for. https://hackage.haskell.org/package/mtl-2.2.1/docs/src/Control.Monad.Cont.Class.html#MonadCont isn't that helpful
13:02 <Acer> quchen, how is fmap using the monadic bind?
13:02 <Acer> from the do notation
13:02 <ongy> ahh, just found it. I had to search for callCC not for the lifting functions. That makes more sense
13:03 <quchen> Acer: fmap f mx = do { x <- mx; pure (f x) }
13:03 fendor joined
13:03 <quchen> :t fmap
13:03 <lambdabot> Functor f => (a -> b) -> f a -> f b
13:03 faberbrain joined
13:03 <quchen> :t \f mx -> do { x <- mx; pure (f x) }
13:03 <lambdabot> Monad m => (t -> b) -> m t -> m b
13:03 <Acer> quchen, the type class constraint on fmap is Functor not Monad
13:04 <Acer> so how can you use bind
13:04 <Acer> and return
13:04 <quchen> Acer: But every Monad is also a Functor. Just like every Ord is also an Eq.
13:04 <quchen> So you can use fmap in every monadic context. :-)
13:04 <Acer> what? no we are talking about a functor context
13:05 <quchen> :t [fmap, \f mx -> do { x <- mx; pure (f x) }] -- See, they’re compatible. We can put them both into the same list.
13:05 <lambdabot> Monad f => [(a -> a1) -> f a -> f a1]
13:05 cluzz joined
13:05 balor joined
13:05 <Acer> when you write the functor instance and implement fmap, you can't use the monadic bind
13:05 <quchen> Acer: Oh, I get it, you meant that my do-solution is more special than your <$> solution.
13:05 <quchen> That’s correct.
13:06 <quchen> But I thought maybe the do-notation helps understanding what happens, assuming your thing is also a monad.
13:06 dsh joined
13:06 <quchen> If it’s not also a monad, you can’t use do-notation, that’s right.
13:06 <quchen> (Up to experimental language extensions)
13:07 <Acer> so how did <$> turn into do notation?
13:07 <Acer> in intToDie <$> state (randomR (1, 6))
13:07 <quchen> (<$>) = fmap, by definition.
13:07 <quchen> And if you have a monad, you can implement fmap in terms of it.
13:07 <quchen> instance Functor Foo where fmap f mx = do { x <- mx; pure (f x) }
13:07 <Acer> no you have to implement functor and applicative first
13:08 <quchen> No you don’t. All instances have to be there, but not in order :-)
13:08 <Acer> before you implement monad
13:08 <quchen> Yup. https://github.com/quchen/articles/blob/master/fbut.md#reversed-type-class-instances
13:08 maninalift joined
13:09 <quchen> Well, nope. Depending on what you mean. Anyway, look at the link above.
13:10 <quchen> Acer: There are plenty of Functor instances in GHC itself that have the default Functor instance I wrote above. Source: I wrote them ;-)
13:11 <quchen> Sometimes it’s easy to implement the monad, and then just copy+paste the Functor/Applicative definitions to save some time and thinking.
13:11 <quchen> For example, if you have a lawful Monad, you also have a lawful Functor and Applicative if you just use »fmap = liftM, pure = return, <*> = ap«. :-)
13:11 inad922 joined
13:11 <quchen> (The downside is that Functor and Applicative often have more efficient, but semantically equivalent, definitions for fmap etc.)
13:12 <Acer> in intToDie <$> state (randomR (1, 6)) is state (randomR (1,6)) of type
13:12 <Acer> State StdGen Int ?
13:12 <quchen> Yes, that is plausible.
13:13 <quchen> state (randomR (1,6)) carries the generator state, and returns an Int (in range [1,6]) when performed.
13:13 <Acer> and it has a function of type StdGen -> (Int, StdGen) inside it
13:13 <quchen> Yes.
13:14 <Acer> so how does it make sense to fmap over that?
13:14 <Acer> i mean you need 2 fmaps
13:14 <Acer> or something
13:15 <Acer> one fmap to lift over the State monad and one to lift over the function inside it, since intToDie takes Int as argument
13:15 pleax joined
13:15 <Acer> in fact that might not be even enough
13:15 <quchen> Acer: State is the only functor here, we don’t have to scope »into the function«.
13:15 plutoniix joined
13:16 asthasr joined
13:16 <quchen> Somewhere, there’s a definition of what it means to »fmap over a State«.
13:16 <Acer> quchen, intToDie needs a Int
13:16 <quchen> Agreed.
13:16 slidercrank1 joined
13:16 <quchen> fmap needs an (a -> b) and an (f a), where f has a Functor instance.
13:17 <quchen> (State s) has a Functor instance.
13:17 dbmikus joined
13:17 <Acer> if you fmap over the State monad you get the value inside which is a function of type StdGen -> (Int, StdGen)
13:17 <Acer> thats not an int
13:17 <Acer> so you need to fmap again
13:17 <quchen> No, fmap does not »unwrap« the State! fmap for State has type (a -> b) -> State s a -> State s b
13:18 <quchen> The purpose of fmap is not having to look into the State at all! :-)
13:18 <quchen> It just says »I’ll transform the a to a b there and that’s it«
13:19 <quchen> »unwrapping« the State to give you the »StdGen -> (Int, StdGen)« is what »runState« does, but that’s entirely unrelated to monads, it’s a special function that only exists for State.
13:19 unK_ joined
13:20 xall joined
13:20 <Acer> i think i get it
13:20 aib joined
13:20 <quchen> fmap :: Functor f => (a -> b) -> f a -> f b. The key realization here is that (State s) is a suitable choice for (f).
13:20 <quchen> And then you can stop thinking because it is already baked into the fmap :-D
13:21 <quchen> The point of fmap is so you don’t have to worry about mangling the state, passing it on to the right places and what not.
13:21 cpennington joined
13:21 <quchen> You can use State without fmap etc, but it’s a terrible experience of variable twiddling.
13:21 <Acer> rollDie' = intToDie <$> state (randomR (1, 6))
13:21 <Acer> liftA3 (,,) rollDie rollDie rollDie
13:21 <Acer> what about that ^
13:22 <quchen> liftA3 is like multi-fmap. fmap takes a unary function and one value; liftA3 takes a ternary function and three values.
13:22 <quchen> :t fmap
13:22 <quchen> :t liftA3
13:22 <lambdabot> Functor f => (a -> b) -> f a -> f b
13:22 <lambdabot> Applicative f => (a -> b -> c -> d) -> f a -> f b -> f c -> f d
13:22 <quchen> »n-ary fmap« is precisely what Applicative is good for.
13:22 <Acer> is f = StdGen ->
13:22 <quchen> (pure is 0-ary fmap.)
13:23 <quchen> f = State StdGen
13:23 <Acer> ok
13:23 <quchen> f Int = State StdGen Int
13:23 <quchen> liftA3 (,,) :: Applicative f => StdGen Int a -> StdGen Int b -> StdGen Int c -> StdGen Int (a,b,c)
13:24 <Acer> i think its f Die = State StdGen Die in this case
13:25 <Acer> since rollDie' :: State StdGen Die
13:25 oish joined
13:25 <quchen> Since State is also a Monad, you can write it using do-notation instead, which I often find a bit clearer.
13:25 <quchen> do { x <- rollDie; y <- rollDie; z <- rollDie; pure (x,y,z) }
13:25 <quchen> Yup
13:27 mfukar joined
13:28 <Acer> yeah thats way more obvious
13:28 zeroed joined
13:28 sgflt joined
13:28 benma joined
13:29 jj_ joined
13:29 suica joined
13:29 jchia_ joined
13:34 lukaramu_ joined
13:35 Iskarlar joined
13:35 JeanCarloMachado joined
13:37 ystael joined
13:37 <suica> any other collections of problems like https://wiki.haskell.org/H-99:_Ninety-Nine_Haskell_Problems, maybe a bit more difficult?
13:38 <codedmart> I am not sure if this makes sense. I am not sure the best way to explain it, but how do you do something along these lines in Haskell: https://gist.github.com/codedmart/5a4e5871b88ec27cc6dc53f7debeda46
13:38 jluttine joined
13:39 <cocreature> suica: hackerrank has a lot of challenges of varying difficulty and you can use haskell for most of them
13:40 Kreest__ joined
13:40 meba joined
13:41 mohsen_ joined
13:41 <cocreature> codedmart: one way is to use "data AnotherPartialOfType = Some | SomePartial SomePartialOfType". whether that makes sense depends on your application. in most cases I would probably just keep the types completely separate and prefix the names to avoid collisions
13:42 xall joined
13:42 oisdk joined
13:44 <codedmart> cocreature: I am writing an Api using Servant and want to only allow certain `SomeType` on certain routes. Not sure I understand how your suggestion would help.
13:45 bigos joined
13:45 cspollard joined
13:46 Rodya_ joined
13:47 <cocreature> codedmart: if you are using servant, can’t you just use SomeType, DataKinds to get types for each constructor and then have a list of kind [SomeType] that shows the allowed content types?
13:47 <cocreature> similar to the list of content types servant uses
13:48 refold joined
13:48 <codedmart> @cocreature Possibly, not knowledgable on DataKinds at the moment :). I will look into that.
13:48 <lambdabot> Unknown command, try @list
13:48 dfeuer joined
13:48 mizu_no_oto_work joined
13:48 kadoban joined
13:48 <cocreature> codedmart: you don’t need DataKinds, you can just use "data Some = Some", "data Other = Other", and so on and then have a list of kind [*]
13:48 mr_sm1th joined
13:49 <cocreature> I guess you don’t even need the constructor "data Some" should work
13:49 <suica> cocreature: thanks!
13:50 koneko joined
13:52 eacameron joined
13:52 ubsan_ joined
13:53 ziocroc2 joined
13:53 <quchen> suica: Write a function that splits a list in two parts of equal length (±1 element) that works even for infinite lists
13:54 <quchen> splitHalf [1..] = ([1..], ⊥)
13:54 ziocroc joined
13:54 <quchen> splitHalf [1..10] = ([1..5], [6..10])
13:57 erisco joined
13:57 <quchen> For finite lists, splitHalf xs = splitAt (length xs `div` 2) xs
13:57 <cocreature> that’s a nice exercise :)
13:58 Boomerang joined
13:58 eschnett joined
13:59 cdg joined
13:59 hackal joined
14:00 <merijn> quchen: Now you have me wondering whether my splitHalf works for that case
14:01 e14 joined
14:01 <erisco> now split an infinite list in half
14:01 <merijn> I don't think it does :\
14:01 <Acer> i would expect this to throw an error saying theres no monad instance but thats not the error i get http://lpaste.net/353492
14:02 `^_^v joined
14:02 <erisco> what error do you get?
14:02 <Acer> http://lpaste.net/353494
14:02 <quchen> Type mismatch, I guess
14:02 <merijn> Sadly, I don't think I can make my efficient split work for infinite lists
14:02 <erisco> splitting infinite lists in half is trivial
14:03 <quchen> merijn: What’s your effective split?
14:03 <merijn> quchen: Well, not sure if it's actually efficient compared to foldr/build fusion, but it was to demonstrate some simple things anyway: https://gist.github.com/merijn/c163cc106fd245d1cf2e
14:04 <erisco> Acer, I suppose it prioritises that error because it finds instances later
14:04 <quchen> merijn: Split via DList?
14:04 faberbrain joined
14:04 <merijn> quchen: + tortoise and hare, yeah
14:05 <quchen> Tortoise and hare is what makes my puzzle work as well
14:05 <merijn> quchen: Yeah, if you rip out the DList you can make it work :)
14:06 <erisco> Acer, g is a function, remember, so think about what (a, s) <- g is
14:06 <quchen> Gotta go!
14:07 <Acer> erisco, i have seen some cases where they do value <- function
14:08 <erisco> (->)a is a Monad, so you may have seen that used, sure
14:08 <Acer> i think its something like \x -> g x >>= \y -> ...
14:08 alanb99 joined
14:08 alanb99 left
14:08 <erisco> how much do you know about Monad?
14:09 jluttine joined
14:09 <erisco> well I'll make it easier. You don't need anything Monad related to write fmap
14:10 pleax joined
14:10 beanbagula joined
14:11 chlong joined
14:11 <erisco> start this way... fmap f (Moi g) = p what type does p have?
14:11 mohsen_ joined
14:13 sphinxo joined
14:13 <Acer> fmap f (Moi g) = Moi $ \s -> let (a, s) = g s
14:13 <Acer> in (f a, s)
14:13 <Acer> well that compiles
14:13 henriksod joined
14:14 sgflt joined
14:14 dfeuer joined
14:15 <Acer> erisco, where do i get runMoi
14:15 <Acer> runMoi ((+1) <$> pure 0) 0
14:15 Iskarlar joined
14:15 <Acer> oh nvm
14:16 <erisco> are you following a tutorial? that is a confusing question
14:16 mada joined
14:16 <Acer> erisco, i am following the book
14:17 <Acer> i get a weird error
14:17 <erisco> which book? we don't have just one
14:17 <Acer> * Non type-variable argument in the constraint: Applicative (Moi s)
14:17 asmyers joined
14:17 <Acer> when i do runMoi ((+1) <$> pure 0) 0
14:17 <erisco> you need FlexibleContexts or something I imagine. the error message will tell you
14:17 <Acer> haskell programming from first principles
14:17 marsam joined
14:17 <Acer> erisco, yeah it says that
14:17 <Acer> whats that about
14:17 <sphinxo> is there a name for a function that has all it's arguments applied, yet it hasn't been evaluated yet?
14:17 zeroed joined
14:18 <merijn> sphinxo: Not really, because that's not something observable in Haskell
14:18 <erisco> there is an official Haskell spec (called "The Haskell YYYY Language Report"), either 1998 or 2010
14:18 <erisco> GHC is a compiler which implements this spec, but it also adds a bunch of features
14:19 <erisco> so to get those other features you have to enable them
14:19 rcat joined
14:19 <sphinxo> ok thanks, what about the name of a function that you map with
14:20 <Cale> Nothing special
14:20 <sphinxo> functions are functions I guess
14:20 <Cale> sphinxo: btw, it can be a little bit unclear what "all its arguments" actually refers to
14:21 sidei joined
14:21 <erisco> @remember sphinxo functions are functions I guess
14:21 <lambdabot> Okay.
14:21 <Cale> Every function in Haskell has exactly one parameter, and those which appear to have more are really just producing other functions as their result
14:21 <Cale> The compiler may (and does, fairly aggressively) optimise this
14:21 wraithm joined
14:21 <erisco> um, well, there is sort of something like sphinxo is talking about, and that is constructors
14:22 <Cale> But conceptually at least, you only ever supply one argument to a function.
14:22 <Acer> erisco, whats flexible contexts and why do i need it
14:22 zeroed joined
14:22 zeroed joined
14:22 ziocroc joined
14:23 <Cale> Acer: FlexibleContexts lets you have things like Ord (Foo String a), where the type being constrained is not simply applied only to type variables in the constraint
14:23 uncertainty joined
14:23 miklcct joined
14:23 <Cale> er, sorry, where the class is not simply being applied to type variables
14:23 <erisco> Acer, there are restrictions or omissions in the spec. This makes implementations easier but as GHC evolves it pushes past these boundaries
14:23 <Cale> A common example would be something like MonadState Integer m
14:24 <erisco> there are several simplifications to how type classes must be
14:25 <erisco> I don't really care about it, so I just enable the extension and move on with life ;)
14:25 <Cale> Yeah, the Report is initially very very conservative about type classes, and lots of stuff is separated out into language extensions.
14:25 honeymead joined
14:25 <Cale> FlexibleContexts and FlexibleInstances are no worry in any case
14:25 <Acer> i didn't understand that at all
14:25 <Rembane> Have type classes in GHC become simpler (or maybe more lax) over time?
14:25 <Cale> In fact, FlexibleContexts was just part of GHC's behaviour for many years before anyone noticed that it disagreed with what the Report says
14:26 <Acer> do you mean i can have Functor take an argument of kind *->*->*
14:26 <Acer> ?
14:26 <Cale> Acer: So, in Haskell 98 or 2010, when you have a constraint on a function, the class must be applied only to type variables
14:26 <Cale> So, for example, it would be okay to have something like (MonadState s m) => ...
14:27 <Cale> (Maybe I should take a look at the error you're actually getting so that I can explain it in terms of what you're dealing with)
14:27 <Cale> But anyway, if you want to replace that s with a specific type, that wouldn't have been allowed under the original restrictive rules
14:28 whiteline joined
14:28 <Cale> e.g. (MonadState Integer m) => ... would require FlexibleContexts
14:28 <Acer> http://lpaste.net/353496
14:28 <erisco> if this wasn't an extension feature you wouldn't think twice about it
14:28 cluzz joined
14:28 <Cale> Ahh, yeah
14:28 <Cale> You're asking for an Applicative instance for Moi s
14:28 gregman_ joined
14:29 <Acer> no i think i am asking for a functor instance
14:29 <Acer> runMoi ((+1) <$> pure 0) 0
14:29 <Cale> You can write something like Applicative f with Haskell 98, but not Applicative (Moi s)
14:29 <erisco> pure is from Applicative
14:29 <Acer> oh right
14:29 Argue joined
14:30 yezariaely joined
14:30 <Cale> ah, and it's an inferred type too, so you didn't write it :)
14:30 <Cale> anyway, chances are you just need to write that instance
14:30 <Cale> so that the constraint will go away altogether
14:30 <Acer> why can't you be specific when writing MonadState s m?
14:31 <Cale> It's just that the Report was *extremely* conservative when specifying what you could do with type classes
14:31 <Acer> i mean you can write Maybe Int without a problem
14:31 <Cale> In fact, even at the time it was written, GHC could handle that
14:31 <erisco> spec writers add limitations to make implementations easier
14:32 <erisco> that is the why
14:32 <Acer> [Int], Maybe Int, Either Int String
14:32 <Acer> theres no problem with those
14:32 <Cale> Yeah, it's so that if you write a new Haskell compiler, you have a much easier job just getting to the baseline functionality
14:32 <Cale> and then you can start implementing extensions one at a time
14:32 <merijn> Cale: Flexible* is something I really hope goes away in HaskellPrime
14:32 <Cale> merijn: We could probably do without it...
14:33 <Cale> I don't know how tricky anyone's ever found implementing FlexibleContexts
14:33 crobbins joined
14:33 <erisco> they just need to bundle them up... didn't we joke it should be -XKmett?
14:33 <Cale> Well, there used to be -fglasgow-exts
14:33 <Acer> you don't need to enable an extension for those
14:33 <Acer> so why do you need an extension for MonadState
14:33 <erisco> Acer, if you used those in a context you would
14:34 <erisco> there is a difference between contexts and not contexts
14:34 <Cale> Acer: Those aren't type classes
14:34 <Cale> Acer: If you try to write (Ord String) => ... (which is a silly, but valid constraint) you'll also run into it
14:35 mizu_no_oto_work joined
14:35 <Cale> Haskell 98 let you apply type functions to anything you wanted still, it's only the use of type classes which are restricted in that way
14:38 bangtree joined
14:38 <sphinxo> what's the "best practices" way to do pretty printing, instances of some typeclass or functions? syntax highlighting using annotations?
14:38 coltfred joined
14:39 <erisco> I haven't heard of a strong preference in that regard
14:39 <erisco> on the other hand, if you're writing Show instances you need a license
14:39 <Cale> haha
14:39 <merijn> sphinxo: What do you mean by pretty printing instances?
14:40 <sphinxo> as in instance Pretty <sometype> where ...
14:40 <merijn> Right, so defining a pretty printing class
14:40 <sphinxo> vs ppLambda, ppVar,
14:40 <Cale> sphinxo: That is a common approach
14:40 dfeuer joined
14:40 <merijn> I wrote a custome one for my language, but I assume there's something on Hackage too
14:41 <sphinxo> there's plenty
14:41 <sphinxo> I think I've decided on annotated-wl-pprint
14:41 <Cale> Usually people don't need to make sure they all use the same pretty printing class, since it's usually only consumed at the application level
14:41 <sphinxo> over wl-pprint-extras
14:42 <merijn> I liked ansi-wl-pprint
14:42 <merijn> I vaguely remember quchen working on one?
14:42 <merijn> But I might be mistaken
14:42 mson joined
14:43 <quchen> merijn: That is correct
14:43 <quchen> Well, I did work on it, it’s done, but I didn’t come around to taking over wl-pprint yet
14:43 <quchen> Haddock: https://quchen.github.io/ansi-wl-pprint-docdump/wl-pprint-1/index.html
14:44 <merijn> I mainly remember because when I saw it, it was supposed to remove my no 1 annoyance with ansi-wl-pprint :p
14:44 <merijn> The idiocy that is <$> as not fmap >.<
14:45 kosorith joined
14:45 <c_wraith> Hmm. >.< is a perfectly valid operator.
14:45 crobbins joined
14:46 Argue_ joined
14:47 Rodya_ joined
14:48 oisdk joined
14:48 HarveyPwca joined
14:49 <Cale> merijn: I'm pretty sure it predates <$> for fmap
14:49 <Cale> At least, some version of it does
14:49 <Cale> But yeah, that should probably get changed :P
14:51 <ystael> c_wraith: that would be a good name for composition-on-the-error-side, or something :)
14:52 ziocroc joined
14:56 FjordPrefect joined
14:56 Argue__ joined
14:57 mszczygiel joined
14:58 hexagoxel joined
14:58 Tourist joined
14:59 Faucelme joined
15:00 clamchowder joined
15:00 <clamchowder> Hello
15:01 cschneid_ joined
15:01 Limona joined
15:01 refold joined
15:01 <Limona> hello
15:01 <Limona> is there a nice simple example of haskell
15:01 <Limona> without monads and stuff
15:01 hackal joined
15:02 wraithm joined
15:02 <tdammers> Limona: what exactly are you looking for? what's your situation?
15:02 steeze joined
15:02 <Limona> i'm reading the tutorial
15:02 <Limona> on wikibooks
15:02 <tdammers> which one
15:02 <tdammers> ok
15:02 <erisco> fac n = product [1..n]
15:02 <Limona> and i'd actually like to see some examples of simple haskell programs
15:03 <clamchowder> I have no knowledge at all about haskell. I know more popular language like python, C++ etc. But recently I have to write a reader for pandoc, which is written in haskell. My question is: why is pandoc written in haskell? What feature of haskell makes it a better candidate for a document converter?
15:03 <erisco> main = putStrLn "Hello Sailor!"
15:03 coltfred_ joined
15:03 <tdammers> ^ this, pretty much
15:03 asmyers joined
15:03 <tdammers> it's also technically free of monads
15:03 <hackal> Hi, I set up dev environment on Windows following https://atom.io/packages/ide-haskell, works fine but I am getting error that it cannot import System.Random. I guess this should be default package right? Do you have any advice on how to solve this issue?
15:03 <lyxia> clamchowder: the author probably just likes the language
15:04 <merijn> hackal: No, System.Random is from the random package
15:04 <tdammers> clamchowder: haskell is quite well suited for writing parsers and compilers, and since pandoc is essentially architected like a compiler, this makes a lot of sense
15:05 <merijn> clamchowder: Well, two things people would generally agree Haskell (and ML like languages like Ocaml, F#, etc.) are very good at is: writing parsers and dealing with ASTs
15:05 <shapr> Is there anything like Erlang's bit pattern matching in Haskell?
15:05 <benzrf> Limona: that's a little like saying "is there a nice simple example of C without functions and stuff"
15:05 <erisco> Limona, many of the list functions are basic
15:05 <merijn> shapr: Sadly, not as far as I'm aware
15:06 <shapr> I want to parse network packets :-/
15:06 faberbrain joined
15:06 <erisco> in C you write string functions, in Haskell you write list functions
15:06 <benzrf> Limona: monad is the most generally useful interface to the IO type
15:06 <shapr> In Haskell, Lens writes you!
15:06 <tdammers> shapr: are you a coprogrammer?
15:06 <Limona> https://www.schoolofhaskell.com/school/to-infinity-and-beyond/pick-of-the-week/Simple%20examples benzrf
15:06 <Limona> got em
15:06 <shapr> tdammers: I turn code into bugs, is that a yes?
15:06 <tdammers> shapr: <<loop>>
15:06 <benzrf> Limona: that's using the monad interface to the IO type right there...
15:07 <erisco> mm, that's good protein
15:07 <shapr> tdammers: :-D
15:07 <Limona> i know
15:07 <Limona> but it's the best i could find
15:07 <merijn> clamchowder: I would also argue that refactoring/maintaining big projects (such as pandoc) is much easier in pure languages, so since the author of pandoc (presumably) already knew Haskell, it seems like a rather good fit for the problem
15:08 <clamchowder> lyxia, tdammers and merijn: OK thanks.
15:08 <tdammers> Limona: don't fear the monad. One, it's a fairly simple abstraction, it's just a very abstract one; and two, you can ignore most of it and, for now, just focus on what bind (>>=) and return mean for the IO type
15:08 <erisco> Limona, go through and implement all the functions here https://www.schoolofhaskell.com/school/to-infinity-and-beyond/pick-of-the-week/Simple%20examples#data-list
15:08 bodisiw joined
15:08 <clamchowder> merijn: what do you mean by pure language? what is not a pure language?
15:08 <hackal> merijn: doing cabal install random says that I already have random-1.1 installed
15:08 <tdammers> Limona: that is, pretend that the type of return isn't :: Monad m => a -> m a, but just a -> IO a
15:08 <merijn> clamchowder: Pure functional programming means "functions that can't have side-effects"
15:08 <Limona> thanks
15:09 <benzrf> merijn: i'd go a step further and say "evaluating expressions" in general can't have side effects
15:09 <tdammers> Limona: then once you get a feeling for how bind and return work for IO, tackle some other monadic type, e.g. Maybe
15:09 <benzrf> merijn: given that there are expression types besides function app
15:09 <clamchowder> tdammers: is a pandoc reader a parser or a compiler?
15:09 <merijn> clamchowder: You could make a reasonable argument that pandoc is a compiler
15:09 <tdammers> clamchowder: it's the parser part of a compiler, which itself is also a compiler... it depends whether you consider the AST an intermediate of the compiler, or its output
15:10 <erisco> clamchowder, "not a pure language" includes Java, C#, C, C++, Python, Ruby, PHP, JavaScript
15:10 <tdammers> clamchowder: that is, you could say that pandoc as a whole is a a compiler of {input language} -> {output language}, and the pandoc AST is an implementation detail, or you could argue that a Pandoc reader is a compiler of {input_language} -> {pandoc AST}
15:10 <shapr> jlouis: What do you think about parsing binary data in Haskell? Anything later/better than your blogpost post?
15:11 <merijn> clamchowder: Anyway, as a result Haskell drastically reduces the amount of shared mutable state in your project, making it much easier to keep track of what's going on
15:12 <erisco> lets also mention this is not a null language
15:12 <tdammers> erisco: we do have bottoms though
15:12 <shapr> booty call!
15:12 emc2 joined
15:13 <benzrf> clamchowder: ok, you know how when you write an expression like "3 + int(input('type a number'))" in a language like python, the expression gets evaluated to a result value, and in the process it may cause effects or depend on external factors, like printing thigns out and gathering input from the user?
15:14 eklavya joined
15:14 <clamchowder> benzrf: yes
15:14 <benzrf> clamchowder: in haskell, evaluating an expression cannot do that. for example, any expression that results in a number will work exactly the same as just putting the result as a literal
15:15 <benzrf> clamchowder: like an expression such as "sin(x) + 4" - you can always replace that with just the result as a literal and it will not change how the program works
15:15 <benzrf> this is true of all expressions in haskell
15:15 <shapr> @seen jlouis
15:15 <lambdabot> J|ouI$
15:15 <shapr> psh
15:15 zero_byte joined
15:15 <benzrf> clamchowder: that's what "pure" means
15:16 <erisco> well maybe it is a tad more clear if you have two sites in the same context
15:16 skeuomorf joined
15:16 <erisco> so something like (getChar(), getChar()) or whatever Python calls reading a character
15:16 codesoup joined
15:17 takle joined
15:17 <erisco> because with sin(x) + 4 your x can change. you can set x = 4 and get one answer and set x = 5 and get another
15:17 <clamchowder> benzrf: I don't quite get what you mean, what is 'putting the result as a literal'?
15:18 <freeside> shapr: you want to twiddle bits, http://book.realworldhaskell.org/read/code-case-study-parsing-a-binary-data-format.html
15:18 <erisco> it is that in the context of x = y, sin(x) + 4 is always the same
15:19 <erisco> it is always sin(y) + 4, specifically
15:19 <shapr> freeside: are you a member of the atlant freeside hackerspace?
15:19 shafox joined
15:19 <freeside> i used to live in atlanta, but i'm not a member of the hackerspace there, no
15:19 <clamchowder> thanks a lot guys. is there any good resource you can recommend that can teach me writing parser using haskell?
15:20 <Cale> Yeah, benzrf, your example isn't great, because that might be inside a lambda which binds x, and so not always evaluate to the same thing ;)
15:20 <benzrf> Cale: well. ok
15:20 <Cale> Referential transparency is always relative to a particular context
15:20 <Cale> But yeah
15:20 <freeside> clamchowder: there's a good chapter on parsing in the haskellbook.com
15:20 <merijn> clamchowder: Well, do you have any basic Haskell knowledge already?
15:20 <benzrf> clamchowder: well, for example - if i have a line of code like "x = print('hello')", then the print call will result in None - but if i replace that, and just say "x = None", then i change what the program does
15:21 <benzrf> clamchowder: this can never happen in haskell
15:21 <merijn> clamchowder: Real World Haskell has a chapter on Parsec, the exact example have bitrotted a bit over the years, but the underlying principles of how parsec works (and really, how all of the parser combinator libraries in Haskell I know) work hasn't really changed
15:21 <erisco> clamchowder, that's the best place to start imo :)
15:21 <Cale> The main thing is that there's a clear separation in Haskell between expression evaluation on the one hand -- the process of reducing expressions to values for the purposes of matching patterns -- and execution of IO actions on the other.
15:21 _sg joined
15:22 oisdk_ joined
15:22 <shapr> freeside: I can't find any Haskellers in Atlanta, got any tips?
15:23 <Cale> Execution of IO actions can cause your computer to do anything that computers do, and can depend on any number of external factors. But evaluation of expressions is kept separate from that, so if an expression is evaluated twice and the free variables occurring in it are bound to the same things each time, then it'll evaluate the same way, and the only effect this will have is to produce the value which is the result of evaluating the
15:23 <Cale> expression.
15:23 <clamchowder> merijn: I have no haskell knowledge at all..
15:23 govg joined
15:23 <shapr> clamchowder: ooh, you have an excellent adventure ahead of you!
15:24 <Cale> That is, I think, perhaps the most important difference between Haskell and most other languages ready for industrial use.
15:24 <benzrf> clamchowder: you may be a little bit shit out of luck if you don't really want to learn haskell, then... the vast majority of mainstream languages have a bunch of fundamental things in common which haskell doesn't have at all, so moving from any of C, python, javascript to haskell is kind of like starting to program over again
15:24 <Cale> The type system is also a pretty big deal (and factors into this somewhat as well)
15:24 <benzrf> clamchowder: it may be pretty difficult to "just write some code in it without understanding 100% of what you're doing"
15:24 <erisco> except some waste heat and time, which some people like to argue about
15:25 Shatnerz0 joined
15:25 <Cale> erisco: right :)
15:25 <erisco> could be relevant if you depend on spacebar heating
15:25 <Cale> There's some places where this abstraction gets broken a little bit too, like with lazy IO primitives.
15:27 <Cale> (though one could argue that you already executed an IO action, to really understand the behaviour of programs in the presence of lazy I/O requires an understanding of how evaluation is going to happen -- which is why people shy away from using lazy I/O very much)
15:27 <merijn> clamchowder: It'll be rather hard to dive into writing parsers without doing some haskell learning first, since Haskell is rather difficult from most languages you already now (well, unless you know like Ocaml/F#/Swift, then it'll be considerably easier)
15:27 sz0 joined
15:28 <Cale> Parsers are perhaps my favourite thing to write in Haskell though :)
15:28 <erisco> I learned with parsers first
15:28 <Cale> Yeah, I don't think I really understood what the monad abstraction was about until I'd used Parsec :)
15:29 soLucien joined
15:29 <clamchowder> freeside and merijn: I'll check out the haskellbook.com and the Real World Haskell, thanks for the pointers.
15:29 <freeside> shapr: http://lmgtfy.com/?s=d&q=haskell+meetup+atlanta
15:30 <erisco> shots fired
15:30 <freeside> looks like https://www.meetup.com/Atlanta-Functional-Programming-Meetup/ is what you want
15:30 <Cale> clamchowder: http://www.cis.upenn.edu/~cis194/spring13/lectures.html is another nice one to check out
15:30 <merijn> clamchowder: I would say Real World Haskell is...not great, for learning Haskell. It's a bit dated and skips over important details, IMO. It serves as a decent reference for some well-known libraries, though
15:30 uglyfigurine joined
15:31 <shapr> freeside: yeah, I started that meetup
15:31 <merijn> I've heard good things about Haskell Book (and a small, but very vocal minority who seem to hate it), but I haven't read it
15:31 <Cale> I'm not yet really sure what to think about haskellbook.com -- I've heard some good things and some really negative things.
15:31 <erisco> what about LYAH?
15:31 <freeside> lol ok
15:31 <merijn> erisco: Also not great
15:31 <Cale> I like Graham Hutton's book
15:31 <freeside> what have you heard about haskellbook.com, cale?
15:31 <merijn> It was great when it first came out, since the only thing we had was the "Gentle Intro", but...
15:31 <Cale> http://www.cs.nott.ac.uk/~pszgmh/pih.html
15:31 <merijn> @quote Brend Gentle.Intro
15:31 <lambdabot> Brend says: Whoever chose the title "A Gentle Introduction to Haskell" is obviously accustomed to wrestling bears in piranha pits or something.
15:32 <freeside> i have gone through it and i can see how it is perhaps too purist for everyone
15:32 <erisco> geez, Haskell Book is really trying to sell to the defeated mindset
15:32 <freeside> i enjoyed Hutton's book, i also enjoyed the haskellbook.com
15:32 <clamchowder> benzrf: I just wanted to write a converter... but I see your point
15:33 <erisco> is Christopher Allen an IRCer?
15:33 <shapr> yeah, is bitemyapp
15:33 <erisco> I recognised the face
15:33 Miroboru joined
15:33 <shapr> erisco: what do you mean about defeated mindset?
15:34 cdg joined
15:34 <merijn> clamchowder: To give some comparison when I say 'Haskell is rather different from most languages you know', I consider Ruby, Python, JavaScript, and Lua to be "basically the same language if you squint a little" :)
15:34 <erisco> shapr, just based on the messaging at the top of the page
15:35 <clamchowder> Is haskell very mathematical?
15:35 <merijn> You can maybe add Java to that list too
15:35 <shapr> clamchowder: it can be, if you want to do that
15:35 <blackdog> merijn: heh, i've got into so many arguments with that line
15:35 skeet70 joined
15:35 <Cale> clamchowder: It doesn't require you to know much mathematics, but it's very mathematical in a particular sense
15:35 <orion> clamchowder: All computer science is mathematical.
15:35 <erisco> I get it, but I just feel bad reading it :P have some confidence people, it'll be okay
15:35 <merijn> clamchowder: Yes, no, maybe. Do we steal some terminology? Yes. Do those abstractions help? Sometimes. Do you require a math background? No.
15:35 <blackdog> last friday night at a party: "ruby and python are basically the same'
15:35 <blackdog> s/'/"/
15:36 <blackdog> response: "WHAT? HAVE YOU NEVER TYPED 'IMPORT THIS'???"
15:36 eatman joined
15:36 <benzrf> lol
15:36 <blackdog> (i'm great fun at parties honest)
15:36 <Cale> I would also say that if you enjoy programming in Haskell, you would probably also enjoy proving theorems in mathematics -- the mental process involved is similar.
15:36 <shapr> blackdog: wow, harsh
15:36 <shapr> blackdog: how's code?
15:36 <clamchowder> Is the math in haskell mostly category theory?
15:36 <erisco> that's some serious fighting words in those communities to suggest that
15:36 <benzrf> merijn: tbh python and javascript actually do have almost identical semantics
15:36 <Cale> But the raw knowledge required isn't all that similar
15:36 <benzrf> clamchowder: no
15:36 <blackdog> shapr: on hiatus, i guess. jobhunting.
15:36 xall joined
15:37 <shapr> blackdog: relaxing while you look?
15:37 <blackdog> no, not really. it's stressful, i need work to maintain my visa.
15:37 <merijn> clamchowder: No, people associating category theory with Haskell is my pet peeve. (And I say this as a haskell fan and someone occasionally trying to learn category theory)
15:37 <Cale> clamchowder: There's bits of category theory which we've stomped on a bunch so that it would fit inside the language, but it's safe to ignore category theory :)
15:37 <erisco> OO in Ruby is alright but I kinda like how PHP does it more
15:37 <freeside> In the introduction to SICP, Perlis wrote: "It is better to have 100 functions operate on one data structure than to have 10 functions operate on 10 data structures." But in Haskell, you can have 100 functions operating on 100 data structures
15:37 <* erisco> ducks
15:37 <merijn> clamchowder: I would say knowing category theory, has approximately 0 benefit until you're like already writing expert level Haskell :)
15:38 <benzrf> merijn: like seriously, if you look at stuff even like how the object orientation works in javascript and in python, it's shockingly similar
15:38 <shapr> blackdog: oh, I forgot about that, that sucks :-(
15:38 <merijn> clamchowder: If anything, lambda calculus, type theory and logic are the math fields to look at for Haskell. But even then that's mostly optional
15:38 <benzrf> they are honestly almost identical when you strip away the syntax
15:38 <tdammers> IMO the main relationship between Haskell and CT is that CT forms the theoretical underpinnings for many of the abstractions used in Haskell, and that makes the language and its idioms very robust, but it doesn't mean that you need to learn CT in order to use Haskell productively
15:38 beerdrop joined
15:39 <merijn> tdammers: "many of the abstractions" <- which ones, other than functor? And even that one has been pounded into unrecognisability
15:39 <Cale> I think learning category theory is valuable if you want to do it at some point -- especially if you have a more general interest in mathematics -- but it's mostly a diversion from getting things done in Haskell.
15:39 <merijn> tdammers: Monad looks nothing like a CT monad
15:39 <freeside> you don't need to know Latin and Greek to speak English, but if you happen to be a professional fiction author, that'll really set you apart.
15:39 <benzrf> merijn: rephrase bind as join and it does!
15:39 <cocreature> the problem is not learning CT, the problem is that people learn CT before they understand how to avoid space leaks because to a beginner it often seems like it more important than it is
15:39 <Cale> cocreature: right
15:39 <orion> Category theory isn't necessary for Haskell any more than chemistry and heat transfer aren't necessary to drive a car.
15:40 <benzrf> ^
15:40 <freeside> https://www.youtube.com/watch?v=GmgoPd7VQ9Q&list=PLbgaMIhjbmEnaH_LTkxLI7FMa2HsnawM_&index=20
15:40 <merijn> cocreature: Well, my main objection is "learning CT to become better at Haskell" :)
15:40 al-damiri joined
15:40 <freeside> "a monad is just a monoid in the category of endofunctors!"
15:40 <merijn> cocreature: There's so many more worthwhile investments if the goal is "become better at haskell"
15:40 <benzrf> freeside: ok, that phrase is my pet peeve
15:40 <benzrf> freeside: "the" category of endofunctors isn't a thing
15:40 <benzrf> it's specifically the category of endofunctors on Hask
15:40 <tdammers> merijn: I didn't say that Haskell's Monad is literally a CT monad, I said that CT provides theoretical underpinnings
15:40 <benzrf> freeside: every category has an associated category of endofunctors, there is no "the" category of endofunctors
15:41 <erisco> it is like learning physics in order to learn how to drive
15:41 <merijn> Anyway, this kinda gets away from the clamchowder's point of "do I need math" :)
15:41 <erisco> they're related, but you can more directly just learn how to drive
15:41 <benzrf> honestly i wouldnt even say that category theory is to physics as physics is to driving
15:41 <freeside> i'm just quoting some polish dude
15:42 <benzrf> i thikn maybe itd be accurate to say that
15:42 <benzrf> category theory is unreasonably effective for designing haskell abstractions
15:42 <benzrf> :)
15:42 tsmish joined
15:42 <freeside> Hask is not a category! http://math.andrej.com/2016/08/06/hask-is-not-a-category/
15:42 teppic joined
15:42 <* freeside> ducks
15:42 <benzrf> freeside: shhhhhhh
15:42 <benzrf> fast and loose reasoning is morally correct
15:42 <benzrf> :}
15:42 <okeuday_bak> if two cabal packages contain two files that use the same path, they always will conflict, right?
15:43 <freeside> a conflict is just a monoid in the category of file paths!
15:43 <benzrf> shoosh
15:43 pera_ joined
15:43 <okeuday_bak> hehe
15:43 spoonm joined
15:43 nbro joined
15:43 <* benzrf> ponders what a monad on a poset category would look like
15:44 <glguy> okeuday_bak: Sure, if they actually use the same path then they'll conflict, but what path are you thinking of that is the same?
15:44 <nbro> hi guys!
15:44 <freeside> guys and gals, bro
15:44 <erisco> and a new snowclone was invented
15:44 <clamchowder> OK I get it. I'm going to learn some haskell now. Thanks for the discussion :)
15:44 <okeuday_bak> glguy: Foreign.Erlang is currently being used by some GPL alpha code and I would like to use my own file for that
15:44 <nbro> just to make sure, this is an abstract data type: data MyData = MyData { before :: String, after :: String, something :: Int }, not an algebraic data type, right?
15:45 <glguy> okeuday_bak: OK, that's not related to file paths. You can use your own module with that name
15:45 chaptastic joined
15:45 <erisco> nbro, things you write with "data" are algebraic data types
15:45 <glguy> okeuday_bak: Making your own module won't replace the one that is already being used
15:45 <erisco> nbro, abstract data types are ones where you do not have access to the constructors, like Data.Set or Data.Map
15:46 <nbro> @erisco what is an abstract data type in Haskell then?
15:46 <lambdabot> Unknown command, try @list
15:46 <glguy> and if you have a package that depends on both packages that provide that module you'll need to use the PackageImports extension to disambiguate
15:46 <nbro> lol, I forgot this lambdabot gets crazy because of the at
15:46 simukis__ joined
15:46 <okeuday_bak> glguy: I am not using their Foreign.Erlang module, but I was wondering what would happen if I added their package as a dep, and you are saying that my project module will always be used instead of a dep module, right?
15:46 <benzrf> nbro: people normall address in irc using a colon anyway
15:46 <freeside> https://www.reddit.com/r/haskell/comments/38grqx/what_is_the_difference_between_an_algebraic_data/cruxgrq/?utm_content=permalink&utm_medium=front&utm_source=reddit&utm_name=haskell
15:47 <tdammers> nbro: IRC custom for pinging people is to just write their name. No @ or # or whatever required.
15:47 <glguy> okeuday_bak: I'm saying you'll need to use an extension if both modules are available in order to pick one
15:47 preyalone joined
15:47 <tdammers> nbro: or, like this, a colon
15:47 <benzrf> bbl
15:47 <okeuday_bak> glguy: k, cool, thanks for mentioning the PackageImports, wanted to see if there was a way out of that type of problem
15:47 <nbro> erisco: what does it mean to not have access to constructors?
15:47 <erisco> nbro, to make an abstract data type you make an algebraic type in a module and then you do not export the constructors
15:48 <erisco> nbro, it works the same way as in other languages such as C
15:48 wraithm joined
15:48 Rodya_ joined
15:48 <erisco> in C you write the type T in one file and all you expose is the type T *
15:48 <nbro> erisco: ok
15:49 <nbro> erisco: here https://wiki.haskell.org/Abstract_data_type for example, after reading, I didn’t have a clear idea of the difference between abstract and algebraic dt
15:49 <erisco> "An abstract data type is a type with associated operations, but whose representation is hidden."
15:49 <erisco> by "representation" they mean the constructors
15:50 <nbro> erisco: but they also say: “data Tree a = Nil
15:50 <nbro> | Node { left :: Tree a,
15:50 <nbro> value :: a,
15:50 <nbro> right :: Tree a }” is a abstract type
15:50 <juri_> hlint is smarter than me. \o/!
15:50 <erisco> well that's a different sense of the word
15:50 <nbro> 2.1
15:50 <nbro> erisco: then they should be more careful, IMO
15:50 Rodya_ joined
15:50 Acer joined
15:50 <freeside> agreed
15:51 <erisco> I don't know why they follow up with that example actually
15:51 nonzen joined
15:52 <erisco> and saying Integer is abstract is a bit strange, not sure about Float
15:52 <erisco> > (\x -> case x of 0 -> "zero"; _ -> "not zero") 1
15:52 ziocroc joined
15:52 <lambdabot> "not zero"
15:52 teppic joined
15:52 <erisco> > (\x -> case x of 0.0 -> "zero"; _ -> "not zero") 1.0
15:52 <lambdabot> "not zero"
15:52 <erisco> they're not abstract
15:53 <erisco> the literals are constructors
15:53 subttle joined
15:53 bennofs joined
15:54 <erisco> they say at the end of Definition: "In addition, parametrized types can be viewed as a kind of abstract type, because they leave some parts of the data type undefined, or abstract."
15:54 <erisco> so they're acknowledging this is a different meaning of "abstract"
15:55 <erisco> but not so clearly delineated
15:55 <glguy> integer literals are kind of like constructors, but they aren't constructors
15:55 <nbro> erisco, but it’s confusing because they do not clearly state that there exist algebraic data types which do not expose data constructors which are actually the abstract data types
15:55 <nbro> IMO, it’s confusing and it should be changed
15:56 <erisco> nbro, read 2.2 Stack
15:56 <nbro> erisco: I read and this is the problem
15:56 <nbro> they made this confusing on purpose
15:57 <nbro> just to make seem Haskell difficult
15:57 <nbro> it’s not
15:57 augur joined
15:57 <nbro> they talk about two different concepts with the same names
15:57 <nbro> in the same article
15:57 <nbro> just to confuse people
15:57 <erisco> never assume malice where incompetence will suffice ;)
15:57 wraithm joined
15:57 <freeside> this is a good example of a situation where a strongly typed natural language would have avoided the namespace collision
15:58 <erisco> I am just trying to make the joke though. I don't think it is incompetent, but it really didn't need to be the same article
15:58 <erisco> it would have been more clear if they have two articles and linked them together as a disambiguation of the word "abstract"
15:58 <erisco> which Wikipedia does, for example
15:58 <freeside> never attribute to malice what can be explained by excessive abstraction
15:59 <nbro> and IMO these concepts should have different names (just because of these situations)
15:59 <erisco> well that won't happen nbro as computer science is filled with overloaded terminology
15:59 <erisco> just ask what "polymorphic" means
16:00 <erisco> Haskell hasn't decided on all of its terminology, it is also just using what is prevalent
16:00 <nbro> people could at least put some effort in using different terminology for different things…
16:01 <nbro> by the way, regarding my first example, data MyData = MyData { before :: String, after :: String, something :: Int }
16:01 <erisco> but this people you speak of is the unorganised masses. it just happens
16:01 oberstein joined
16:01 <nbro> I thought algebraic data types had data constructors, which eventually accept parameters
16:01 <erisco> glguy, they are kind of like constructors and kind of not, and so not the best two examples to be using
16:01 vektorweg1 joined
16:02 <glguy> erisco: Constructor is kind of name
16:02 <glguy> integer literals are their own thing
16:02 <nbro> but in the case of MyData, what is the data constructor?
16:02 <glguy> nbro: MyData is a data constructor
16:02 Snircle joined
16:02 <glguy> and also there is a separate constructor at the value level
16:03 <glguy> they just happen to be written with the same letters
16:03 <erisco> glguy, I don't know really, because if you just defined data Integer = 0 | 1 | 2 | ... I don't know how you'd tell the difference
16:03 <glguy> err, both a type constructor and a constructor
16:03 <nbro> glguy: if MyData is also a data constructor, then what’s the meaning of the things in the record, that is { before :: String, after :: String, something :: Int }?
16:03 mmn80 joined
16:03 <erisco> then we're just left with a special compiler feature to overload these names for the various types, but that is nothing special
16:04 <Tuplanolla> Pattern matching wouldn't impose `Eq`, erisco.
16:04 medicijnman joined
16:04 <glguy> erisco: Yeah, you can think of it like that. That's just not what constructor means
16:04 <erisco> :t \x -> case x of 0 -> 1
16:04 <Tuplanolla> For a general `Num`, that is.
16:04 <lambdabot> (Num t, Num a, Eq a) => a -> t
16:04 <glguy> nbro: First let's disambiguate and write: data MyData = MkMyData { before, after :: String, something :: Int }
16:05 <glguy> nbro: MyData is now the type constructor, MkMyData is the value constructor
16:05 <erisco> that is a reasonable way to distinguish it Tuplanolla
16:05 <nbro> glguy: ok, so before MyData was both type and data constructor?!
16:05 trism joined
16:05 <glguy> nbro: There are two completely separate namespaces
16:05 <glguy> and MyData existed separately in both
16:06 <nbro> ok
16:06 hackebeilchen joined
16:06 sehnny joined
16:07 <freeside> that overloading problem again
16:07 urodna joined
16:07 <erisco> Tuplanolla, well, I retract that, because we're talking about Integer specifically, and Eq Integer can be dismissed
16:08 JeanCarloMachado joined
16:08 Luke joined
16:09 <Tuplanolla> As noted.
16:09 <erisco> so I wouldn't consider it a shining example of an abstract type
16:09 <erisco> when you've got Data.Map and Data.Set readily available
16:09 <nbro> ok, now if MkMyData is a data constructor, I suppose “before::String, after :: String, something :: Int” are somehow its parameters..?!
16:09 HaskellLord69 joined
16:10 <erisco> you can actually dig into those and see how it works
16:10 fre joined
16:10 danharaj joined
16:10 <glguy> nbro: MkMyData is a constructor declared with record syntax. before, after, and something are field labels
16:10 Sonolin joined
16:10 kuribas joined
16:10 <glguy> Because we have those three fields, the type of MkMyData is 'String -> String -> Int -> MyData'
16:10 boombanana joined
16:11 boombana1a joined
16:11 oberstein joined
16:11 <glguy> and when used as a pattern we can expect it to be applied to 3 other patterns, or to use record syntax as a value and pattern
16:11 revtintin joined
16:12 <nbro> just to make it clearer, can a data type defined with the record syntax as above be defined without the record syntax?
16:12 <freeside> this may be a useful case to consider:
16:12 <freeside> data MyData1 = MkMyData1 String String
16:12 <freeside> data MyData2 = MkMyData2 { before :: String, after :: String }
16:12 <freeside> curried = MkMyData2 "foo"
16:12 Swizec_ joined
16:13 <erisco> record syntax is convenience, but there nothing but a data type underneath
16:14 jmelesky joined
16:14 <freeside> once those lines make sense to you, consider this: data MyData3 = MkMyData3a String String | MkMyData3b { bef :: String, aft :: String }
16:14 <erisco> having projectors is a common need, and updating fields is a common need, and so there is record syntax
16:15 <erisco> you can do everything without it
16:15 <freeside> once MyData3 makese senes to you, the first sentence of https://en.wikipedia.org/wiki/Algebraic_data_type#Theory shold also make sense
16:16 <erisco> 1 inhabitant, 2 inhabitants, 3 inhabitants, ha ha ha
16:17 <raek> as I spend time using boost::optional in my professional journey through C++-land my homesick heart aches longingly for my good old friend Maybe from far away Hanskell-land
16:18 <merijn> raek: Write a DSL (in Haskell!) that generates C++ for you!
16:18 <freeside> indeed, Hutton's entire book on Haskell doesn't even mention record syntax
16:18 <erisco> raek, may you one day not have to visit your variants
16:19 <nbro> first of all, it seems there are different ways of declaring data types, and this is already annoying
16:19 osa1 joined
16:19 osa1 joined
16:20 gcross_ joined
16:20 _sg joined
16:20 <erisco> 'when she was still a doctoral student she participated as “math support” in the construction of a small experimental nuclear reactor in Slovenia. One of the physicsts asked her to estimate the value of the harmonic series 1+1/2+1/3+⋯ to four decimals. When she tried to explain the series diverged, he said “that’s ok, let’s just pretend it converges”.'
16:20 <nbro> you can declare a data type like this: data Day = Monday | Tuesday | … , whose data constructors do not have fields
16:20 <erisco> http://math.andrej.com/2016/08/06/hask-is-not-a-category/ that is gold XD
16:20 insitu joined
16:20 <nbro> and you can do things like this: data MyData1 = MkMyData1 String String
16:21 ramzifu joined
16:21 <nbro> where you could pass around MkMyData1 “sometihng” “else”
16:21 <nbro> I mean, why? Why two different ways to use data?
16:21 <Cale> nbro: Those are both the same way
16:22 <Cale> data Color = RGB Int Int Int | CMYK Double Double Double Double
16:22 <Cale> You can combine them
16:22 <Cale> In general, a data type may have multiple constructors, and each may have fields
16:22 <Cale> (both are zero or more)
16:22 <erisco> two different ways to use data? my friend, that is why it is algebraic! :)
16:22 <freeside> data Color = RGB { r :: Int, g :: Int, b :: Int } is better than RGB Int Int Int
16:23 <Cale> freeside: sure
16:23 <Cale> (I didn't expect anyone to actually use that type ;)
16:23 <nbro> freeside: you say it’s better because you can refer to r, g and b?
16:23 <Cale> Though using record syntax with multiple constructors is awkward
16:23 Habib_ joined
16:23 <Cale> Because your field extractors become partial functions
16:24 <erisco> unless they share the same field, but yes it is not good
16:24 <nbro> so, could we have, say, data Color = RGB { r :: Int, g :: Int, b :: Int } | CMYK {c::Double, m::Double, y::Double, k::Double}?
16:24 <Cale> nbro: yeah
16:24 <freeside> yes, if one regularly pulls individual r/g/b components out of a pixel, then saying 'r pixel' more convenient than doing a pattern match
16:24 <nbro> and also something like this data Color = RGB Int Int Int | CMYK {c::Double, m::Double, y::Double, k::Double}?
16:24 _sras_ joined
16:24 <nitrix> nbro: You could but it's dangerous as `r`, `g`, `b`, `c`, `m`, `y` and `k` are now partial functions.
16:24 <_sras_> What causes the "Failed to unify types" error?
16:24 <erisco> your types do not match
16:24 <nitrix> @let data Color = RGB { r :: Int, g :: Int, b :: Int } | CMYK {c::Double, m::Double, y::Double, k::Double}
16:24 <Cale> (also you just defined a bunch of functions whose name is a single letter, which is... questionable)
16:25 <lambdabot> Defined.
16:25 <nitrix> > c (RGB 0 0 0)
16:25 <lambdabot> error:
16:25 <lambdabot> Ambiguous occurrence ‘c’
16:25 <lambdabot> It could refer to either ‘Debug.SimpleReflect.c’,
16:25 <nitrix> > L.c (RGB 0 0 0)
16:25 <erisco> single letter function names are not so great because variables often are named with a single letter
16:25 <lambdabot> *Exception: No match in record selector c
16:25 <erisco> so if you make a boo boo that'll lead to a confusing error
16:26 cluzz1 joined
16:26 <Cale> Generally names should increase in length as the scope of the thing being defined increases, and shorten with frequency of use
16:26 <nbro> ok
16:26 <nitrix> nbro: As you can see with this Exception, partial functions are to be used sparingly.
16:26 <erisco> alwaysHereAndNeverUsed
16:27 <freeside> that's why I always refer to William Henry Gates III as "Bill"
16:27 <erisco> he's on speed dial is he?
16:27 <Cale> nbro: But you'll eventually come to feel like every other language's types are lacking -- this ability to define types with multiple constructors is really useful
16:27 ego joined
16:27 <Cale> nbro: Consider for example this definition of binary trees holding values of a variable type
16:28 bodisjw joined
16:28 <Cale> data Tree a = Tip | Branch a (Tree a) (Tree a)
16:28 <nbro> so, in summary, everything defined with data is an algebraic data type… there are algebraic data types which are abstract and those hide the data constructors, somehow to make them super flexible… then we have the record syntax, which is just syntactic sugar for declaring data constructors, so that we can access the fields somehow with partial functions, right?
16:28 <nshepperd_> erisco: fun note: if you pretend that sequence converges, you get the euler mascheroni constant, via the Cauchy principle value https://en.m.wikipedia.org/wiki/Riemann_zeta_function
16:28 <Cale> i.e. a binary tree is either the empty tree called Tip
16:28 <erisco> I can survive with side effects, but lack of sum types is murder
16:28 <_sras_> erisco: Doesn't that show up as type mis match error?
16:28 Rainb joined
16:28 <Cale> or it's of the form Branch x l r where x is some value (at the root) and l and r are two subtrees of the same type
16:28 <nitrix> nbro: data Shape = Triangle Base Height | Circle Radius | Rectangle Width Height
16:28 <Cale> e.g. you can now write Branch 0 (Branch 1 Tip Tip) (Branch 2 Tip Tip) :: Tree Integer
16:29 <erisco> _sras_, I cannot remember the specifics. If you paste your code and error we can help
16:29 <nitrix> nbro: renderShapes :: [Shape] -> IO ()
16:29 carlomagno joined
16:29 contiver joined
16:29 <erisco> most languages have anemic sum types which they call "enums"
16:29 <_sras_> erisco: It is in a code created by Template haskell. I am not sure the exact code that triggers it.
16:29 <nshepperd_> erisco: zeta function can answer such questions as what is 1+2+3+... :)
16:30 <Habib_> Anyone know a better name for this effect?
16:30 <Habib_> redirectToSameHostRefererOrRoot = redirect =<< fromMaybe General.URL.root <$> sameHostReferer
16:30 chaptastic joined
16:30 <nbro> Cale: I understand this example: data Tree a = Tip | Branch a (Tree a) (Tree a)
16:30 <_sras_> erisco: this is the full error "Failed to unify types: (ConT Data.Time.LocalTime.LocalTime.LocalTime,ConT DepartureTime)"
16:30 <nbro> my problem was related to the record syntax
16:30 dfeuer joined
16:30 <Habib_> sameHostReferer returns a (Just referer) that's the same host if it can find it from the header, otherwise Nothing.
16:31 <nbro> what the hell is it and what’s the relation between data types declared with record syntax and those without it
16:31 <nitrix> Habib_: Wouldn't it be best to just name it "sameHostRefererOrRoot" ?
16:31 <erisco> _sras_, I don't know based on just that, sorry
16:31 <Cale> nbro: Well, that was aimed at your original examples comparing Day and MyData1
16:31 desku joined
16:31 deskuu joined
16:31 <nitrix> Habib_: This way you can still perform redirections or pass it to other operations, rather than tieing them together?
16:31 danthemyth joined
16:31 oberstein joined
16:31 Noldorin joined
16:31 Luke joined
16:32 <nitrix> Habib_: And use `sameHostRefererOrRoot >>= redirect` at your call sites when needed?
16:32 <Habib_> nitrix, yeah, I thought about that, but I can't think of any other reason I'd need the referer only from the same host, and it's easy enough to change later if necessary.
16:32 <erisco> nbro, do you know what a projector is?
16:32 <Cale> nbro: Record syntax just automatically defines functions for extracting the fields, and enables some additional pattern matching (e.g. you can match just some of the fields, and ignore others), as well as record update syntax
16:32 <suica> is there a better way to do this toy example point-free: \x y -> show [(x, y)] <---> (show .) . ((:[]) .) . (,) that allows you to contain the first two arguments to the `(,)` segment of the composition?
16:33 <Cale> nbro: The underlying type is still the same as one which didn't name its fields, and you can still use the plain non-record syntax with a type that uses it
16:33 <Habib_> But I think I might just go that route, just to keep things under 80 lines.
16:33 <Habib_> 80 columns*
16:33 <nbro> erisco: no, I think
16:33 <suica> basically i'm curious if there's a way to do `show . (:[]) . <something here>` where the <something here> consumes two arguments
16:33 <nbro> at least in Haskell
16:33 <kuribas> suica: I think \x y -> show [(x, y)] is fine
16:33 pleax joined
16:34 <erisco> suica, you can define (:.) f g x y = f (g x y)
16:34 <Cale> nbro: e.g. if I have data Employee = MkEmployee { name :: String, salary :: Integer } then I'm still allowed to write Employee "Bob" 100000
16:34 <Cale> oops
16:34 <nitrix> suica: (.:) = (.) . (.)
16:34 <Cale> nbro: e.g. if I have data Employee = MkEmployee { name :: String, salary :: Integer } then I'm still allowed to write MkEmployee "Bob" 100000
16:34 <Cale> ^^ fixed typo :)
16:34 <nbro> Cale: ok, thanks for the clarifications
16:34 <suica> cool, thanks!
16:34 <Cale> nbro: But I may write MkEmployee { name = "Bob", salary = 100000 }
16:35 <erisco> (id ~> id ~> show . (:[])) (,) is another solution with ~> from TypeCompose
16:35 <nitrix> erisco: I think it should be .: not :.
16:35 <Cale> and I can write stuff like giveRaise n empl = empl { salary = salary empl + n }
16:35 <centril> edwardk: oisdk handed me this: https://gist.github.com/oisdk/92b43b63ee6aba451d5daf55af528d04
16:35 <Cale> Here, salary is automatically defined as a function Employee -> Integer
16:35 <nitrix> erisco: The mnemonic used is that dot represents the amount of arguments .: would be composition a function of one argument with a function of two arguments.
16:36 <Cale> and we use it to get the salary of our parameter employee empl
16:36 <Cale> and then add n
16:36 <kuribas> :t curry (show . (:[]))
16:36 <lambdabot> (Show b, Show a) => a -> b -> String
16:36 <nbro> Cale: wait, what’s this MkEmployee { name = "Bob", salary = 100000 }? Is it you initializing a value of type Employee so that you can assign to a “variable
16:36 <centril> nitrix: what's the (.) . (.) operator called again ?
16:36 <nbro> ?
16:36 <freeside> if you think of a record as an object, basically you're spelling out the attribute accessor
16:36 <Cale> Yeah, that makes a new Employee value
16:37 <nitrix> centril: dot ?
16:37 mhealy joined
16:37 ph88 joined
16:37 <Cale> I could make a definition if I like, but I didn't there
16:37 <centril> nitrix: no, not (.)... (.) . (.)
16:37 <MarcelineVQ> nitrix, centril: it's an owl, I swear, nnnnothing else at all
16:37 <kuribas> suica: curry (show . (:[])) but I think it obfuscation.
16:37 <nbro> @let Employee = DCEmployee String String
16:37 <centril> MarcelineVQ: xd xD XD :D
16:37 <lambdabot> .L.hs:170:1: error: Not in scope: data constructor ‘Employee’
16:37 <nitrix> centril: Some people say owl, some people say dot. Even though it's three dots.
16:38 <centril> nitrix: it wasn't a real question ^^
16:38 <Cale> @let data Employee = DCEmployee String String
16:38 <lambdabot> Defined.
16:38 <nbro> oh, sorry
16:38 <nbro> forgot the “data"
16:38 <kuribas> :t singleton
16:38 <lambdabot> error:
16:38 <lambdabot> • Variable not in scope: singleton
16:38 <lambdabot> • Perhaps you meant one of these:
16:38 <Cale> actually, let's change that
16:38 <Cale> @undefine
16:38 <lambdabot> Undefined.
16:38 <centril> nitrix: it's a: "I know the answer to the question already, but it is awkward to say it..."
16:38 <Cale> @let data Employee = DCEmployee String String deriving (Eq, Ord, Show)
16:38 <lambdabot> Defined.
16:38 <Cale> There, just a little extra functionality so that we can play with it
16:38 <nitrix> centril: I don't know what you know already. I'm just content with answering trying to help. But now it's insulting.
16:39 <nbro> @let a = DCEmployee “name” “surname”
16:39 <lambdabot> Plugin `eval' failed with: Enum.toEnum{Word8}: tag (8220) is outside of bounds (0,255)
16:39 <Cale> what the
16:39 <cocreature> nitrix: in https://www.youtube.com/watch?v=seVSlKazsNk it’s called the “blackbird” operator
16:39 <centril> nitrix: It was a joke ;)
16:39 <Cale> nbro: Oh, you're using curly quotes
16:39 <Cale> @let bob = DCEmployee "Bob" "Marley"
16:39 <lambdabot> Defined.
16:39 <Cale> > bob
16:39 <lambdabot> DCEmployee "Bob" "Marley"
16:40 <Cale> > case bob of DCEmployee name surname -> surname
16:40 <lambdabot> "Marley"
16:40 <centril> Cale: damn, with @let you can do wicked n-tuple programming over IRC
16:40 Swizec_ joined
16:40 <erisco> kuribas, but it is the best solution for exercising the often forgotten specialisation
16:40 <nbro> Cale: you have defined before a value using the curly braces, i.e. MkEmployee { name = "Bob", salary = 100000 }, could I also use curly braces for data types not declared with the record syntax?
16:40 <centril> cocreature: nice link, thanks
16:40 <cocreature> nbro: no
16:40 <Cale> nbro: Nope, to use the record syntax, the type has to be defined with it.
16:41 <nbro> ok
16:41 <Cale> With one exception: you're always allowed to use {} after a constructor to ignore all its fields
16:41 <Cale> (when pattern matching)
16:41 <centril> suica: http://hackage.haskell.org/package/pointless-fun-
16:41 <erisco> > id (+) `id` id 1 `id` id 1 -- stop the madness!
16:41 <lambdabot> 2
16:41 <freeside> wait, cale, can you give an example of that?
16:41 <Cale> Sometimes you only care about which constructor something was built with, and not the contents of its fields, which is useful
16:41 <MarcelineVQ> erisco: you're going to start one of those fmap avalanches :>
16:41 balor joined
16:42 vektorweg11 joined
16:42 <ph88> in my file i have ints :: Traversal' a Int but when i do :t ints in ghci i get ints :: (Applicative f, HasTokens a) => (Int -> f Int) -> a -> f a does that mean that Traversal' creates arrows ?
16:42 <Cale> > case Just 5 of Nothing -> 0; Just {} -> 1
16:42 <lambdabot> 1
16:42 <Cale> Of course, with Maybe, that's a bit silly
16:42 <nitrix> erisco: id (id (+) `id` id 1 `id` id 1 {- stop the madness! -})
16:42 <Cale> But sometimes you have a type with many fields
16:42 <centril> freeside: isArray :: AST.Type -> Bool
16:43 <Cale> and you want to make a definition which is resilient when you add more :)
16:43 <centril> as an example of what Cale wrote
16:43 <nbro> it’s kind as useful as the _ when pattern matching with lists then?!
16:44 <Cale> Yeah, if you'd otherwise be writing a pattern like Foo _ _ _ _
16:44 Apocalisp joined
16:44 <Cale> It might be nicer to write Foo {}
16:44 <Cale> and you can do that regardless of whether Foo was defined with record syntax
16:44 <nbro> nice!
16:44 <nbro> I really like Haskell
16:44 <freeside> thanks, i did not know that.
16:44 <Cale> Yeah, I think I learned that like a year after most of the rest of the language ;)
16:45 simendsjo joined
16:45 <centril> nbro: you can also use RecordWildCards and do Foo {..} to get out the fields in your constructor as variables bound to the names you have in your record
16:45 <Cale> One of those cute things you tend to only discover if someone tells you or you read the Report carefully
16:46 <nitrix> I believe you can also pattern match on some specific record constructors too.
16:46 <Cale> yes
16:46 <nitrix> foo Bar { baz = ... } = ...
16:46 <Cale> (but that *will* require record syntax of course)
16:46 <Cale> It's a nice way to make definitions somewhat resilient to changes in the data type
16:46 <Cale> though that's not always a positive thing
16:47 <Cale> Sometimes it's nice to be reminded by the compiler that something might need to change
16:47 <centril> nbro: for example: data Person { age :: Int, name :: String } ... case p of Person {..} -> putStrLn $ unwords ["Hello", name, ",", "age:", age]
16:47 moongazer joined
16:47 <Cale> Yeah, that's the RecordWildCards extension
16:47 <MarcelineVQ> {} is nice with as-patterns, to see if a value is using a specific constructor, and use that value, without caring about what's inside: bar x@Foo{} = functionforFoovalues x
16:47 <centril> oops, forgot the = Person part
16:47 <erisco> nbro, did Cale explain what a projector is?
16:48 <centril> MarcelineVQ: you can also combine that with lenses for great success
16:48 <Cale> I didn't -- what's a projector? :)
16:48 <nitrix> RecordWildCards is neat too, bringing the record fields in scope.
16:48 <erisco> I feel like I am being trapped now
16:48 <centril> nitrix: it's a bit controversial i've heard... no idea why tho...
16:48 <MarcelineVQ> centril: do you have an example of what you mean?
16:48 <Cale> A fair number of people are not fans of RecordWildCards, but I think it can look pretty cute if you're simulating OO in Haskell.
16:48 <Cale> centril: One reason is that it binds variables without naming them
16:49 <centril> MarcelineVQ: do functionforFoovalues inline on x with lenses
16:49 <nitrix> foo Bar {..} = baz
16:49 <Cale> another is that it implicitly shadows a bunch of definitions while it's at it
16:49 wraithm joined
16:49 <centril> MarcelineVQ: for example in AST traversal
16:49 <Cale> So it can be hard to refactor and manipulate code which uses RecordWildCards
16:49 <nitrix> Cale: I thought it named them by the name of the record fields o.o ?
16:49 <Cale> It does.
16:49 <Cale> But the definition of the type might be far away
16:49 <nitrix> Oh. Oh you mean it can become really obscure.
16:49 <Cale> and if the definition of the type changes, new variables can get bound and shadow other stuff
16:49 <centril> Cale: oh, right
16:50 <nitrix> Fair point,
16:50 <erisco> first I'll make Cale happy (hopefully) and say that a projector is an eliminator for a product type
16:50 <Cale> I would normally say "projection"
16:50 <centril> Cale: same here
16:51 <freeside> you're just projecting
16:52 <nbro> another question, if a data type like data TC = DC1 | DC2 is a sum type, what’s a product type (I know it exists this concept, but I would like to hear your explanations)
16:52 <erisco> (Int,String) is an example of a product type, a product of Int and String
16:52 <monochrom> data P = MkP Int Bool Char is product of IntxBoolxChar
16:53 contiver joined
16:53 <ph88> how can i resolve the type ambiguity in this code? https://bpaste.net/show/d0a58220ed48
16:53 <erisco> it is what you get in every other language, it is the sum types that are usually missing
16:53 <nbro> ah ok
16:53 <nbro> as I was thinking
16:53 <Cale> nbro: Something like data Foo = Foo Integer String
16:53 subttle joined
16:53 <Cale> Is a "product" of Integer and String
16:53 soLucien joined
16:54 <nbro> ok, thanks! Makes sense
16:54 <erisco> now for intersection types
16:54 <centril> nbro: this might be relevant: http://manishearth.github.io/blog/2017/03/04/what-are-sum-product-and-pi-types/
16:56 eatman joined
16:56 <centril> nbro: they are called product types because the possible values of (A, B) is the cartesian product of the sets A & B, so A x B
16:56 Prutheus joined
16:56 <centril> nbro: sum types are called so because the possible values of Sum A B is all values in A + and all in B , so Either a b = a + b
16:57 <erisco> now integrate the Taylor series
16:57 <centril> erisco: pi types?
16:58 <erisco> there is a particular blog post on ADTs where they derive the list zipper algebraically
16:59 <centril> nbro: there are even fractional types, so you can say: T * 1/T = T
16:59 <erisco> https://chris-taylor.github.io/blog/2013/02/10/the-algebra-of-algebraic-data-types/
16:59 <nbro> centril: yeah, I got that, thanks anyway ;)
17:00 <centril> nbro: =)
17:00 earldouglas joined
17:00 <centril> erisco: nice =)
17:00 <erisco> "What does it mean to subtract, divide or take square roots of types?"
17:00 <byorgey> T * 1/T = T ? Your fractional types behave strangely
17:01 BlueRavenGT joined
17:01 <centril> byorgey: whoops :P
17:01 <byorgey> also, I wouldn't say "there are fractional types". No one really knows how to interpret fractions as types.
17:01 <centril> byorgey: T * T * 1/T = T, obviously
17:01 mbw joined
17:02 <byorgey> hehe
17:02 <erisco> there is this idea where you introduce an object, like i, that normally can't exist
17:02 <centril> byorgey: the interpretation deals with futures and promises
17:03 <erisco> and a way of understanding this is you're just inserting a blank
17:03 <byorgey> centril: are you referring to this paper https://www.cs.indiana.edu/~sabry/papers/rational.pdf ?
17:03 <erisco> and you try and eliminate it
17:03 <erisco> so you can find a proof where it wasn't necessary at all
17:03 <erisco> as far as I understand it anyways, which isn't so much
17:04 theelous3 joined
17:04 <byorgey> centril: that paper was never published because it has some major flaws. The system described in the paper has only trivial models.
17:05 romanandreg joined
17:05 koneko joined
17:05 <centril> byorgey: :(
17:05 <erisco> well you might have 1/T as a multiplicative inverse, why not
17:05 <byorgey> I meant what I said: interpreting fractions as types is an open question and an active area of research.
17:06 <erisco> the question is if you can find a proof that does not involve 1/T
17:06 <erisco> i.e. transform the proof with 1/T to one which does not, for all such proofs
17:06 <byorgey> erisco: sure, that's fine. I was talking specifically about *interpreting fractions as types* themseles.
17:06 <erisco> if you can do that then you're safe using 1/T
17:06 <centril> byorgey: right, that part I get and agree on
17:06 <erisco> right, well, seems like nonsense to me as well :P
17:06 <nbro> Haskell is like: once you try it, you feel like the other languages have been designed by an amateur lol
17:07 b4ff3r joined
17:07 <centril> nbro: I get that feeling every time I move to a more strongly and statically typed language
17:07 <nbro> at least the languages that I know, which are quite old
17:07 faberbrain joined
17:07 <nbro> Haskell isn’t too young to
17:07 <nbro> *too
17:08 <freeside> meanwhile, over on #agda ... a similar conversation is happening ...
17:08 <erisco> I have wondered how deep the circles go
17:08 <centril> nbro: like <random dynamically typed language> => C => Rust, untyped lambda calculus => haskell => agda
17:08 <erisco> who is laughing at #agda who isn't merely an equal
17:08 <centril> freeside: haha, my thoughts exactly
17:09 teppic joined
17:09 <erisco> has anyone else had these thoughts? if you can one day stumble on Haskell, and another on say, Coq/Agda/Idris/DT-whatever, could there be yet another mind-blowing thing out there?
17:09 <nbro> looking forward to learn Rust
17:09 <nbro> :D
17:09 eschnett joined
17:10 <centril> erisco: in any case, #haskell vs. #agda are just squabbles within Chalmers University of Technology
17:10 <taktoa> nbro: that's because most other languages have literally been designed by amateurs, in the sense of being created by people who are not people-who-are-paid-to-study-programming-languages :^)
17:10 castlelore joined
17:10 castlelore joined
17:11 <centril> taktoa: hmm... well... don't know if that applies to C & C++
17:11 <freeside> don't all such recursive relations find a fixpoint in category theory?
17:11 <taktoa> centril: yeah, the problem with those was being designed too early
17:11 <centril> freeside: i cant parse that statement
17:11 subttle joined
17:12 <centril> taktoa: by early, do you mean: "in a time where computer resources were a fraction of what they are today" ?
17:12 <freeside> i mean the ultimate "mind-blowing thing out there" is category theory
17:12 caumeslasal joined
17:12 raichoo joined
17:12 <erisco> somewhere high in the Himalayas are a secretive organisation of computer scientists who already know if P=NP, and whether braces and semicolons are better than whitespace
17:12 <taktoa> centril: that and "a time where knowledge of computer science was a fraction of what it is now"
17:12 ner0x652 joined
17:12 leat joined
17:12 <taktoa> C was designed before the HM type inference algorithm was known
17:12 <Tuplanolla> Lisp has been around since 1958.
17:12 <centril> taktoa: hmm... well... what about C++ ?
17:13 <nbro> even though I think it’s not fair to compare, say, Rust to C++
17:13 oberstein joined
17:13 <centril> nbro: Rust is a modern language with lessons from the recent decades, unlike Go, which is a regression
17:13 <nbro> It’s normal that future languages will be better than the ones we currently have
17:13 <nbro> centril: exactly
17:13 <centril> nbro: no... that is just not true...
17:14 <nbro> centril: I’m not saying all of them
17:14 <centril> nbro: Go is a prime example of a future language being worse than something before it
17:14 <erisco> I say bring back column sensitive syntax
17:14 <nbro> centril: I intended that we’re going to learn from the past mistakes
17:14 <centril> nbro: yes, at least some of us ;)
17:14 <taktoa> centril: C++ was designed in the early 1980s, and HM was unknown-enough in 1985 that Damas independently published his PhD thesis on the algorithm in that year
17:15 gillesmajor joined
17:15 <erisco> poor soul
17:16 marfoldi joined
17:16 <centril> nbro: others prefer the route: "learning a complex language takes too much time, so I'll write code that will move all bugs to runtime instead of dealing with them at compile time"
17:16 <erisco> move fast, break things
17:16 <nbro> centril: lol, who said that?
17:16 path[l] joined
17:16 <centril> nbro: these people make Dijkstra roll over in his grave
17:17 <centril> nbro: the inventors of Go, paraphrased
17:17 conal joined
17:17 <okeuday_bak> is Data.Monoid imported by default like Prelude in GHC 7.10.3
17:17 <okeuday_bak> ?
17:17 <freeside> Richard Gabriel: "Worse is better!" Go: "Hold my beer."
17:17 <shapr> Richard Gabriel: "Better is Worse!"
17:17 <centril> okeuday_bak: try to use (<>) w/o importing Data.Monoid
17:17 Swizec joined
17:17 <glguy> okeuday_bak: No, Data.Monoid isn't imported by Prelude in 7.10.3 nor in the current 8.0.2
17:17 <taktoa> I mean modern type theory was invented (for mathematics) by Martin-Lof in 1972 so my limit for blaming people for not knowing How To Do Type Systems™ is the year 2000
17:18 <okeuday_bak> centril: why shouldn't I import it though?
17:18 <taktoa> or maybe the mid 90s
17:18 <centril> okeuday_bak: you have to import it
17:18 <centril> okeuday_bak: to use (<>)
17:19 <centril> taktoa: why 1972 and 2000, why are these 2 years related?
17:19 tommd joined
17:19 zaquest joined
17:19 govg joined
17:19 <centril> seems arbitrary
17:19 <taktoa> centril: 2000 is arbitrary
17:19 <centril> 1972 is not, obviously
17:19 <taktoa> I'm merely justifying the line I've drawn in the sand
17:19 <taktoa> 30 years seems reasonable
17:19 <centril> taktoa: right, 30 years is a bit much tho...
17:19 <centril> 10 years seems reasonable
17:19 <erisco> in the sands of time, how poetic
17:20 <centril> taktoa: language designers should be aware in max 5 years - programmers in general maybe 20 years
17:20 <freeside> you need about 10 years for a generation of grad students to catch up with the literature, and then another 10 years for those grad students to become professors
17:20 <freeside> those professors share the ideas, and then you need another 10 years for the students under those professors to move those ideas into industry
17:20 <freeside> then you need another 10 years for the commercial implementation to mature and become popular
17:21 <freeside> so, total T = 40y
17:21 <centril> freeside: is that an after-the-fact rationalization ?
17:21 <erisco> and 10 years to wake up, 10 years to shower and get dressed, 10 years to eat breakfast
17:21 <taktoa> freeside: I think it's more like 5 years for each of those stages
17:21 <centril> erisco: waking up takes minimum of 20 years.
17:22 <taktoa> especially because T = 40y would imply that dependent types should be mature and popular by now :P
17:22 <mbw> So I've been trying to work my way through tekmo's talk about beautiful folds: https://github.com/Gabriel439/slides/blob/master/munihac/foldmap.md#applying-applicatives . The example with "average = (/) <$> sum <*> product" is supposed to be efficient, however for me there seems to be a slowdown of several orders of magnitude, compared to the hand-written average. This is what I wrote:
17:22 <taktoa> wait I got the direction of the inequality wrong lol
17:22 <mbw> http://lpaste.net/353498 . Note that I had to modify it somewhat because of Semigroup. Given the compiler output from "-Weverything", i.e. the warnings about non-inlineable functions from Data.Monoid/Data.Semigroup, and the profiler output (I can't make read Core), what should I conclude is the reason for this?
17:23 <centril> taktoa: interestingly, Rust "recently" moved away from H&M
17:23 <erisco> mbw, are you compiling with -O2 ?
17:23 <mbw> Yes.
17:24 <taktoa> well HM is the only reasonable basis for a type system, but the actual HM typechecking algorithm is old hat by now
17:24 <mbw> I'd use -fllvm, but it seems GHC only supports it till 3.7. Still, this is way slower than what tekmo claims in his talk/slides.
17:24 <erisco> mbw, in that case I authorise you to employ -O3, everyone brace yourselves
17:25 <taktoa> in particular, there have been two developments: 1. SMT solvers got fast enough to be interesting in the early 2000s and 2. bidirectional typechecking is a lot more appealing of a way to implement a type inference algorithm
17:25 <mbw> I thought -O3 didn't exist!?
17:25 <okeuday_bak> centril: thanks
17:25 <mbw> Doesn't seem to make much of a difference.
17:25 <centril> taktoa: bidirectional typechecking involves?
17:26 <taktoa> watch Conor McBride's talk "Worldly Type Systems"
17:26 <centril> taktoa: thanks
17:26 <taktoa> np
17:26 <mmaruseacph2> suppose I have a f :: MoandError CustomError m => m a and want to use it where I need a f :: IO a. I'm getting a "cannot match IOException with CustomError" at the moment. Is there a way to map between the two? Or just ignore the CustomError, as here I don't care about it
17:27 <centril> taktoa: <3 Connor McBride and his rant about unicode in the Agda standard library
17:27 <mmaruseacph2> s/MoandError/MonadError
17:27 <centril> "No fucking unicode!"
17:27 <erisco> should get him and Linus in a room together
17:28 <centril> taktoa: https://twitter.com/pigworker/status/764410137884909568
17:28 <centril> erisco: hah, Torvalds is in a league of his own...
17:29 <okeuday_bak> centril: I don't understand why GHC 7.10.3 doesn't want me to import mempty from Data.Monoid, it is fine with 8.0.1
17:29 <erisco> "Computer Science is a science only when we're desperate. When we're getting it right, it's easier than that." -- Conor McBride
17:30 xall_ joined
17:30 <mbw> Is there a clean way to inline functions from base, which ghc doesn't "want" to inline, i.e. can't be specialized automatically?
17:30 <centril> erisco: "NVIDIA, Fuck you!" -- Linus Torvalds
17:31 <erisco> after spending a month in lecture on the subject, and writing an essay, I think this one sentence says it all
17:31 <okeuday_bak> "The import of ‘mempty’ from module ‘Data.Monoid’ is redundant" why does this happen in GHC 7.10.3?
17:32 romanandreg joined
17:32 <centril> okeuday_bak: dont know about mempty... but (<>) conflicts with Data.Semigroup iirc
17:33 <okeuday_bak> centril: the import of (<>) is working for me, it seems
17:33 redmq joined
17:33 <erisco> I can't understand the unicode hate though... set up a compose key
17:34 <centril> okeuday_bak: λ> :t (<>) ==> error in ghci
17:34 <centril> :t (<>)
17:34 <lambdabot> Monoid m => m -> m -> m
17:34 <centril> meh
17:34 <erisco> → looks so much nicer than ->, and is easily typed
17:34 cardboard64 joined
17:34 <erisco> λ better than \, ⇒ better than =>, and so on
17:35 schell joined
17:35 <centril> erisco: because hitting the key for latex => unicode, + then writing "to" takes more time than ->
17:35 <okeuday_bak> centril: k, so it may make sense to define my own, but still that requires me to be able to import from Data.Monoid, I am attempting to be selective about my imports but it seems that GHC is angered by this
17:35 _sg joined
17:35 <centril> okeuday_bak: why are you selective about your imports ?
17:35 <schell> hi all - i’m having a hell of a time tracking down a <<loop>>
17:36 <erisco> centril, for me it is three keystrokes, so an extra cost of one
17:36 <okeuday_bak> centril: just to be clear about what is coming from where and make things less ambiguous
17:36 <erisco> there are some annoying ones like ⊆ but it is doable
17:36 <centril> okeuday_bak: just do: import Data.Monoid ((<>), mzero)
17:36 <schell> it seems i have some code that runs fine in my executable cabal project, but when i move it into my library it errs with <<loop>>
17:36 <erisco> and it is a satisfying result
17:36 <schell> have you guys ever run into this?
17:37 <centril> okeuday_bak: always be explicit about imported functions and data types, it's a good thumb-rule
17:37 <schell> my intuition is that laziness should be the same regardless of where the code lives
17:37 <centril> erisco: it also makes writing code that much more editor-dependent
17:37 a3Dman joined
17:37 t7 joined
17:37 <centril> erisco: without an editor that can do this for you, you become dependent on copy pasting symbols
17:38 <erisco> does it? *shrug* I just have software that runs between the keyboard and application
17:38 <centril> erisco: what do you do if all you are stuck with is nano on a headless server?
17:38 <erisco> well I still have no issues because of how my software works, it is not editor dependent
17:38 <okeuday_bak> centril: mzero doesn't appear to exist though, at least in older versions
17:38 <centril> okeuday_bak: oops... mempty
17:39 <centril> λ> :t mzero
17:39 <erisco> if all you had was an editor dependent solution then I can see why that'd suck
17:39 <centril> mzero :: MonadPlus m => m a
17:39 <okeuday_bak> centril: yeah, I am doing "import Data.Monoid ((<>),mempty)" but then GHC 7.10.3 says "The import of ‘mempty’ from module ‘Data.Monoid’ is redundant"
17:40 <centril> erisco: hmm.. software between keyboard and app seems fragile... it has to only do this for certain apps
17:40 cdg_ joined
17:40 fiddler joined
17:40 <centril> okeuday_bak: ok, so do import Prelude hiding (mempty) if you want to be specific
17:40 <centril> okeuday_bak: I would just do import Data.Monoid ((<>)) and use mempty from Prelude
17:40 <okeuday_bak> centril: k, i c, I didn't realize mempty was in Prelude too
17:41 <erisco> centril, I don't know, I didn't implement it, but yes there has to be support from the OS to facilitate this
17:41 <centril> okeuday_bak: it is, but (<>) is not
17:41 <okeuday_bak> centril: k, thanks
17:41 <erisco> you have to register your process to take over keyboard input after a particular key is pressed
17:41 <erisco> or some trigger like that
17:41 <erisco> obviously the OS has features like this for things like sticky keys (joy!)
17:41 <erisco> and alt+ctrl+del and so on
17:42 <centril> erisco: this feels like super brittle if you do this via SSH... how is the middle-keyboard-hook software going to know that a certain "app" is running in the terminal over SSH?
17:42 <erisco> what does a certain app have to do with it?
17:42 <osa1> any persistent users here? how do I specify default value of a `[Text]` column in a table? `default` syntax uses backend-specific syntax but I don't know how is `[Text]` translated to SQL types!
17:43 <erisco> you press the compose key, now the compose software intercepts all keyboard input until it yields
17:43 ziocroc joined
17:43 Rodya_ joined
17:43 <erisco> you type your compose sequence and the compose software sends the effective character as though the keyboard sent it
17:43 moongazer joined
17:43 <centril> erisco: I only want to translate keyboard input of <unicode-start-trigger>+latex-command-name iff the target of the input is an editor for haskell, for example
17:43 Miroboru joined
17:44 <erisco> I don't know why you'd want that, but okay
17:44 <centril> erisco: well... otherwise the <unicode-start-trigger> would do this for all applications...
17:44 <erisco> yes, that is the point
17:45 a3Dman joined
17:45 oberstein joined
17:45 <centril> don't know if I'm comfortable with relinquishing a key on my board to just this
17:45 <erisco> a single key that can enable hundreds of new characters?
17:46 <centril> erisco: I don't have many keys that are strategically and egonomically placed
17:46 <centril> you can't just pick any key anywhere on the keyboard, it has to be close to WASD + Ctrl + Shift + space
17:46 <erisco> I use caps lock
17:46 <freeside> https://www.jwz.org/blog/2016/09/searching-for-finally-got-my-emacs-setup-just-how-i-like-it-yields-excellent-results/
17:46 <shapr> centril: custom input mode in emacs?
17:46 <centril> shapr: fuck emacs...
17:47 neophytes joined
17:47 <shapr> centril: be nice
17:47 <shapr> or else
17:47 <centril> shapr: right... "I don't like emacs"
17:47 <centril> =)
17:47 <shapr> centril: see, that's perfectly fine
17:48 <centril> shapr: I blame Conor McBrides wonderful use of language ^,-
17:48 <shapr> I don't have Swedish keys on my keyboard, but swedish-postfix works great for me.
17:48 <shapr> centril: Conor is certainly expressive.
17:48 <centril> <3 eufemisms
17:48 <neophytes> Hello friends,I am receiving an error with the following source code: http://pastebin.com/rSixQLgt of The IO action ‘main’ is not defined in module ‘Main’. How can I go about fixing it? I assume Haskell needs a main method, but I don't know how to define one
17:49 <centril> shapr: swedish-postfix?
17:49 <erisco> neophytes, if you are just toying around remove your module declaration
17:49 <neophytes> what is a module declaration exactly? haha
17:49 <shapr> centril: yeah, it's an input method for emacs that lets me compose aa -> å for example
17:49 <erisco> the line that begins "module ..."
17:49 wraithm joined
17:50 <centril> shapr: oh, writing swedish a lot ?
17:50 amit_r joined
17:50 <koala_man> neophytes: if you want to be able to type in "double 4" and things like that interactively, use ghci instead of ghc
17:50 <neophytes> The only other Haskell file I have has the source code: main = putStrLn "Hello world!"
17:51 <neophytes> ok
17:51 animated joined
17:52 Luke joined
17:52 <shapr> centril: I do write a decent chunk of Swedish, yes.
17:52 <shapr> centril: I'm just saying, there are other options for unicode input
17:53 <centril> shapr: so you're a swede?
17:53 <centril> (I wonder how many % of #haskell are Swedish, and how much overrepresentation there is)
17:53 <shapr> Nah, I'm from Alabama. Where are you from?
17:54 <Rembane> Några stycken.
17:54 phyrex1an joined
17:54 <shapr> telia.com suggests Sweden, but that's not always true
17:54 <centril> shapr: Sweden, Gothenburg, @ Chalmers University of Technology, the capital of haskell, agda, etc. =)
17:54 <Phillemann> Can I listen on a specific host using scotty (e.g. localhost instead of I just see a port.
17:55 insitu joined
17:55 <centril> shapr: I've heard haskell is more popular in Europe while OCaml is more popular in the states... is there any truth to that?
17:56 <t7> anyone use an auto source formatter for haskell?
17:56 path[l] joined
17:56 oberstein joined
17:57 <shapr> centril: I'm not convinced. OCaml is originally from INRIA, so it's certainly popular in France.
17:57 <shapr> centril: I also don't have a huge pile of usage statistics, so it's hard to say.
17:57 jmelesky joined
17:57 <centril> shapr: right =)
17:57 <mbw> Ok I just noticed something. I get decent performance when I define a Monoid instance for my data type only. However, when I follow GHC's advice and define Semigroup as well, with Monoid.mappend = (<>), this results in a significant slowdown.
17:58 <shapr> t7: already using https://github.com/jaspervdj/stylish-haskell ?
17:58 <centril> shapr: Coq as well - but Thierry Coquand moved to Chalmers
17:58 <shapr> centril: but I've met a pile of Haskell users in Boston and other US cities; but not here in Atlanta
17:58 <shapr> centril: right, that's a good point
17:59 <centril> He's a nice lecturer
17:59 <mmaruseacph2> How can I use a `f :: MonadError CustomError m => m a` as a `IO a`? I'm getting a `cannot match IOException with CustomError` at the moment.
18:00 connrs joined
18:01 <monochrom> Perhaps you should make it MonadError IOException m?
18:01 <centril> mmaruseacph2: you have to actually run the specific f and get out some representation that you can convert to an IO a
18:01 <shapr> centril: oh, lucky you! I've met and chatted with Aarne Ranta, John Hughes and a bunch of other Chalmers people, but not recently.
18:01 blueonyx joined
18:02 yrid joined
18:02 muesli4 joined
18:02 Jesin joined
18:02 <neophytes> My source code is simply: main::IO () double x = x + x quadruple x = double (double x) -- I get the following error: The type signature for ‘main’ lacks an accompanying binding. What should I do to fix it?
18:02 sssilver joined
18:02 <neophytes> I guess I'll use ghci but I'd like to get experience with ghc
18:02 <centril> shapr: anecdote about Aarne Ranta: he let people write exams in the PLT course in like 7+ languages...
18:02 <monochrom> define mina.
18:02 <monochrom> err, define main.
18:02 <shapr> centril: wow! cool
18:02 <neophytes> how do you go about defining main?
18:03 <monochrom> main = print "hello world"
18:03 <geekosaur> mhw, I think Semigroup's <> is missing some optimization RULES that Monoid's has; this is a matter of the ecosystem catching up with recent ghc
18:03 <monochrom> or whatever code you want main to run.
18:03 <centril> shapr: tho he wasn't the examinator for this year tho
18:03 <shapr> centril: I used Rant's GF to write a Swedish teaching webapp at one point, it would construct random sentences and ask for the match in either Swedish or English
18:03 umoukun left
18:03 hydraz joined
18:03 <neophytes> ok so like this? main = double x = x + x quadruple x = double (double x)
18:04 <geekosaur> it may be somewhat improved in the upcoming 8.2, because Semigroup is better integrated in general; but the current Monoid v Semigroup setup is rather hacky and nobody likes it much, aside from that it mostly maintains backward compatibility
18:04 <monochrom> No, that will be a syntax error.
18:04 <neophytes> then I don't know what to do
18:04 <mmaruseacph2> monochrom: I wish I could do that
18:04 <freeside> shapr: i'm planning to learn GF ... is that code available online anywhere?
18:04 <mmaruseacph2> centril: thanks, going to try it
18:04 <monochrom> What do you want the main program to do?
18:04 <erisco> main is just another definition in your program, like double and quadruple
18:04 <centril> shapr: hmm... how does that work given that natural languages are non-formal and stochastic in nature?
18:04 <neophytes> I want the main program to execute: double x = x + x quadruple x = double (double x)
18:05 <neophytes> so I can then compile the program and run commands
18:05 <monochrom> No, that makes no sense.
18:05 <freeside> so say main = quadruple
18:05 <shapr> freeside: I think it's gone forever, but it's really easy to do once you understand GF
18:05 <geekosaur> centril, they still have some fairly well defined rules (just, odd ones sometimes)
18:05 <monochrom> That will be a type error.
18:05 <freeside> with the appropriate decorations
18:05 <neophytes> so I can do things like take (double 2) [1,2,3,4,5,6]
18:05 <centril> geekosaur: depends on the language... some are highly irregular
18:05 <neophytes> ok freeside
18:05 contiver joined
18:06 <monochrom> That is really something for the REPL.
18:06 <erisco> what you want to do is forget about main and just load it in ghci, if you want to do that
18:06 <neophytes> ok
18:06 <shapr> centril: GF supports a subset of natural language that fits into the dependently typed setup Ranta put together, but it has a surprisingly large range
18:06 <neophytes> ill forget trying ti compile it then
18:06 <erisco> ghc is for making executables, ghci is for interacting with definitions
18:06 <centril> shapr: cool
18:06 <geekosaur> yes, but for English at least you can cover a large number of question cases with just verb inversion. I couldn't say how Swedish works
18:06 <neophytes> ok
18:06 robotroll joined
18:06 <shapr> iirc, I think GF even handles some of the Indian subcontinent languages that have a separate word structure for single/double/triple/many
18:07 <geekosaur> (verb inversion: "foo does work" -> "does foo work?" this sometimes requires expanding a verbed adjective into a helper verb + adjective, as one would normally say "foo works" here, but that too is highly formulaic in many cases)
18:08 <centril> geekosaur: "Jag kommer springa." - "Kommer jag springa?"
18:08 <geekosaur> er, s/adjective/adjectival verb/ except that's not the right term)
18:08 sobaken joined
18:08 <geekosaur> heh. I am actually not that surprised because Swedish and ENglish descend from a common North Germanic root
18:08 faberbrain joined
18:09 <mbw> geekosaur: Ok, I guess that at least saves me from asking about this on SO, which I would've done otherwise. I will assume this to be a known problem from now on.
18:09 <geekosaur> (English got some Germanic-tainted French mixed in though :)
18:09 <centril> geekosaur: english grammar is highly scandinavianized
18:09 <erisco> you can throw a question mark on anything and make it a question?
18:09 <geekosaur> verb inversion is usually involved although you'll often notie ESL folks omitting it because their languages don't do that
18:09 <jle`> yes you can?
18:09 <erisco> because minimally you end up with "is this statement true"?
18:10 <geekosaur> (note folks from India in particular but also that that uncommon among Romance language speakers)
18:10 <geekosaur> also English is fleible enough that you can usually understand the intent even if ti's not grammatically correct
18:10 <shapr> t7: have you tried/seen hindent and/or stylish-haskell ?
18:10 <geekosaur> but this is #haskell not #linguistics, so.
18:11 <shapr> but it could be #linguistics if we all install GF :-P
18:11 <t7> shapr: nope i will check them out
18:11 <erisco> just talk about attribute grammar parsers
18:11 ertesx joined
18:11 <freeside> neophytes: because the customer is always right, what you want is probably something like: import System.Environment; double x = x + x; quadruple = double . double; main = do myargs <- getArgs; print $ quadruple $ read $ head myargs
18:11 <monochrom> I know exactly what to say on this. :)
18:11 rgr joined
18:12 <shapr> freeside: ooh, good answer
18:12 <centril> geekosaur: English = Anglo-frisian, roman invasion (latin nouns), viking invasion (scandinavian grammar + nouns like Phil Coul-son), french invasion (nouns), invading everyone else (in chronological order)
18:12 <geekosaur> yep
18:12 <centril> geekosaur: english grammar was highly simplified by vikings
18:12 <geekosaur> but you can do a surprising amount just with the anglo-saxon subset
18:12 <shapr> freeside: I'll dig through and see if I can find my GF translation tutor, but I just deleted a huge pile of my Haskell source code from 99-2005 so it may be gone forever.
18:13 <monochrom> http://spl.smugmug.com/Humor/Lambdacats/i-7QXhZMR
18:13 <geekosaur> which is easily understood by Swedish speakers for some reason :p
18:13 <shapr> Mind you, I also found a copy of edwardk's Lir project and two games written by others, so that made the code spelunking worthwhile.
18:13 <neophytes> import System.Environment; double x = x + x; quadruple = double . double; main = do myargs <- getArgs; print $ quadruple $ read $ head myargs
18:13 <centril> geekosaur: hmm... I think I wouldn't understand the anglo-frisian settlers in England
18:13 <shapr> I found a crack attack clone (curry attack) and a pacman game in Haskell.
18:13 <freeside> shapr: oh, bummer. well, thanks for the offer!
18:13 <neophytes> wow that looks complicated
18:13 <neophytes> lol
18:14 <neophytes> ill stick with ghci for now
18:14 <freeside> i'm sure i will just pick it up as i go along.
18:14 <monochrom> Oh, this one is simpler: http://spl.smugmug.com/Humor/Lambdacats/i-NLLt4fx
18:14 <geekosaur> centril, likely but you're not talking to them :)
18:14 <neophytes> I'm trying to get used to to doing some toy problems
18:14 <edwardk> shapr: i've thrown out so many different low level intermediate representations over the years i have no idea which one you have =)
18:14 <centril> geekosaur: reading text as well
18:14 <shapr> edwardk: this was the beginning of your x86_64 -> x86_64 recompiler project from 2008
18:14 <shapr> edwardk: do you have a more recent version?
18:14 <Cale> neophytes: You should try keeping (at least) two windows open: one with your text editor with a .hs file open in it, and the other with ghci open to that same .hs file
18:14 <edwardk> ah
18:15 <Cale> neophytes: whenever you save your changes, type :r in ghci to reload them and try them out
18:15 <edwardk> shapr: https://github.com/ekmett/jitplusplus <- this thing?
18:15 <neophytes> ok @ Cale
18:15 <edwardk> i should redo that in modern c++
18:15 Rodya_ joined
18:15 <geekosaur> for practical purposes you can subfdivide modern English into Anglo-Saxon, Norman French overlay, and later additions from everywhere. The Anglo-Saxon and French subsets are substantial duplicates of each other, so you can say quite a lot with either one
18:16 <shapr> edwardk: yeah, but this version was entirely Haskell
18:16 <edwardk> ah
18:16 <centril> neophytes: one thing you can try is hole-driven-development: http://matthew.brecknell.net/post/hole-driven-haskell/
18:16 <shapr> That is, the version I found in my ~/src/haskell/Lir/ dir
18:16 <shapr> edwardk: it even says I helped you get around a prickly bit of the code, and that doesn't seem very likely :-P
18:16 nycs joined
18:16 <edwardk> probably with a nanojit style backwards assembler code emission thing?
18:17 <geekosaur> even edwardk had to start somewhere :p
18:17 <neophytes> 'k
18:17 <* neophytes> back to programming
18:17 <centril> geekosaur: I think the changes from the viking invasions make English quite different than say German...
18:17 <edwardk> shapr: well, at one point you actually did know haskell ;)
18:17 <* edwardk> ducks
18:18 <geekosaur> English isn't a lot like South German at all; what it has from that actually came via the Normans
18:18 <geekosaur> the preserved Anglo-Saxon influence is highly Scandinavian
18:19 <centril> geekosaur: Wouldn't English grammar structure be more similar to German had the vikings not invaded?
18:19 <Phillemann> I'm not sure how to best google this, so: Is there any modern haskell extension for defining record field accessors so that they don't clash with other functions/accessors?
18:19 <shapr> edwardk: yeah, I'm trying to reinstall Haskell in my brain
18:19 <centril> Phillemann: https://ghc.haskell.org/trac/ghc/wiki/Records/OverloadedRecordFields/DuplicateRecordFields
18:19 cdg joined
18:20 <geekosaur> Phillemann, no extension as such yet althouh DuplicateRecordFields gets you partway there. you generally do that with a lens package currently (not necessarily full ekmett lens)
18:20 LeNsTR joined
18:20 <geekosaur> OverloadedRecordFields is still in development; more of it will be in 8.2 but it'll stll be incomplete
18:20 <Phillemann> How would I do that with lenses?
18:20 <nbro> hi guys gain!
18:20 <Phillemann> I know about makeLenses, but does that help with name clashes?
18:20 <nbro> *again
18:20 <geekosaur> yes
18:20 <geekosaur> because it makes typeclass instances
18:21 <nbro> I’m implementing a GapBuffer data type and I’ve defined it as follows
18:21 <nbro> data GapBuffer = GapBuffer { text :: String, cursor :: Int } deriving (Show)
18:21 Thra11_ joined
18:21 <nbro> what do you think about it?
18:21 <monochrom> There is no gap. :)
18:21 <nbro> I’m required only to derive Show
18:21 <centril> geekosaur: edwardk went full Lens. Never go full lens!
18:21 <geekosaur> roughly, instance Has (some_representation_of_a_field_name) MyRecordType where ...
18:21 <nbro> :D
18:22 <Phillemann> geekosaur: Isn't that makeClassy?
18:22 <geekosaur> depending on the lens package, that representation may be a Symbol (type level String, sort of) or some token derived from the field name
18:22 <edwardk> nbro: gap buffers are usually defined with two buffers that are easily appended/prepended to.
18:22 <nbro> yeah
18:22 <edwardk> nbro: e.g. data GapBuffer = GapBuffer { reversedPrefix :: String, suffix :: String } -- now you can move the cursor in O(n) for distance n
18:22 <geekosaur> Phillemann, yes, isnt makeLenses the generic interface that also works for deriving accessors for other ADTs and such?
18:22 <nbro> but in case of Haskell it may be more convient just to keep track of the cursor
18:22 subttle joined
18:22 <Phillemann> In any case, don't I have to define the record field accessors anyway? As in "data Foo = Foo { _x :: X }", which then again clashes.
18:23 <geekosaur> ekmett lens is not limited to recird fields the way e.g. fclabels is
18:23 Berra joined
18:23 <edwardk> back (GapBuffer (f:fs) rs) = GapBuffer fs (f:rs); back g = g
18:23 <monochrom> No, String = [Char] is a singly linked list and it takes forever to "where is the 100th item?"
18:23 <geekosaur> yoju do need to decladre them specially but that can incllude arbitrary prefixes to disambiguate
18:23 <edwardk> nbro: the point of a gapbuffer is O(1) update at the cursor. your structure is O(n) to update at the cursor
18:23 <geekosaur> you may have to tell it what prefix scheme you are using
18:23 wraithm joined
18:24 <* geekosaur> sighs, gets more coffee
18:24 <edwardk> its basically a 1-finger tree
18:24 <monochrom> Not to mention that the [] API is actually pretty cumbersome for tasks like "I want to insert something between the 100th and 101th items"
18:24 <edwardk> or a fingered list
18:24 a3Dman joined
18:24 <nbro> edwardk: why would it be O(n), because I would need to create another GapBuffer when updating the cursor?
18:24 <erisco> "here's the 100th character!" "great, can you also get me the 99th?" *groan*
18:25 <centril> geekosaur: I'd say the most important diff btw french & german vs. english & swedish is that in french, verbs are conjucated by the subject, like: "j'ai, tu as, nous avons" which they are not in english: "I have, you have, we have" ... with the exception of "I am"
18:25 contiver joined
18:25 <edwardk> nbro: inserting a character at the nth position in a string takes O(n) work
18:25 <nbro> edwardk: oh, didn’t think about it
18:25 <monochrom> Locating the nth position already takes that much time.
18:26 <geekosaur> nbro, you need to traverse and split the Text at the cursor point. a gap buffer stores it split at the cursor, so you trade move cost (which amortizes somewhat) for fast insert at the cursor which is the most common case
18:26 steeze joined
18:26 <nbro> and the reason is that I’ve been implemeting only functions that require me to update the cursor
18:26 <edwardk> insert 0 c xs = c:xs; insert n c (x:xs) = x:insert (n-1) c xs; insert n c [] = ... whatever you want to do here
18:26 nadirs joined
18:26 <geekosaur> if moving is much more common than insertion, or insertion can be done in bulk operations (insert large string instead of insert character) then your representation can be better
18:27 <edwardk> gapbuffer gives you O(1) access to the cursor, in exchange for O(n) cursor moves. finger trees give you O(log (min(k,n- k)) access to any element.
18:28 <mpickering> Does anyone know if there are plans for munihac again this year?
18:28 <edwardk> in theory, though the space story is bad, a 3 finger tree represented by somehting like data GapSeq = Gap (Seq Char) (Seq Char) -- using Data.Sequences gives you O(1) update at the cursor, and O(log n) moves
18:29 <edwardk> a mutable gap buffer is used though because the reads/writes are sequential and have nice cache coherence / branch prediction
18:29 anton joined
18:29 <centril> btw... does all allocation done by GHC happen on the heap, or are parts done on the stack? for example when you do strict evaluation ...
18:29 <edwardk> so making a big memory buffer, and just sliding the content to the bottom/top of it is often quite a performance win if you don't need persistence
18:29 <centril> (the code generated by GHC... not in GHC itself...)
18:30 <edwardk> centril: a lot of strict stuff happens on the stack for Int#'s and the like
18:30 <edwardk> and once the code is determined to be strict, ghc is good at optimizing that stuff
18:30 Habib_ joined
18:30 MrcRjs joined
18:31 cyborg-one joined
18:31 <centril> edwardk: right, but in general, if GHC can't determine that something is strict, it must live on the heap ?
18:31 path[l] joined
18:32 <monochrom> Still, a list node is still on the heap, even if it is a strict list you coded up yourself.
18:32 MoALTz joined
18:32 <edwardk> in general yes
18:32 darjeeling_ joined
18:32 <centril> monochrom: if it is a linked list yes, but not if it is sequential (and has a size known at compile time)
18:32 <centril> edwardk: thanks, that makes sense =)
18:33 <edwardk> centril: array types etc. get allocated out on the heap too
18:33 <monochrom> That is also force. Even GHC's built-in bytearray is on the heap.
18:33 <monochrom> s/force/false/
18:34 <centril> edwardk: so there is no way to get a sequential array on the stack ? why not ?
18:34 <monochrom> The cause of the whole big fuss about "boxed type != lifted type"
18:34 <edwardk> An Array# in GHC is a pointer to an object that lives on the heap that holds pointers to other objects. a ByteArray# lives out on the heap and holds onto a bunch of bytes that can represent other stuff
18:35 insitu joined
18:35 <centril> edwardk: didn't know that, thanks
18:36 <edwardk> centril: in theory you might come up with some form of stack frame tweak to hold onto big flat arrays of bytes or stack pointers, then tweak the compiler to desugar the construction of an array that doesn't leak out of scope anywhere in the following code, followed by the deallocation of the array after doing a bunch of mutations to it to put the array on
18:36 <edwardk> the stack, and change the stack representation to look enough like the haskell array rep to proceed, but nobody ever bothered.
18:36 <edwardk> heap allocations are about the same price as a stack allocation, both are just pointer bumps
18:37 <edwardk> haskell arrays aren't c arrays
18:37 <edwardk> a c array has a fixed size. haskell arrays carry their size
18:37 <monochrom> If you write so much as "data X = MkX {-# UNPACK #-} !Int {-# UNPACK #-} !Char", you still have your MkX node on the heap not stack.
18:37 <edwardk> we can't 'inline' arrays in a c like fashion into data types either.
18:37 <Cale> Also if we're talking about Array, a Haskell array can have elements which are defined recursively in terms of one another, and which get evaluated lazily.
18:38 <centril> Also... Does referential transparency in a language like haskell require garbage collection? So you can't have an FP language + manual memory control ?
18:38 <edwardk> centril: laziness without gc is quite difficult to define meaningfully
18:38 <monochrom> Could you write your own Haskell compiler that puts it on the stack? Yes. Does GHC do this? No. Why? No one has bothered yet.
18:38 <Cale> centril: Note that the Haskell FFI does have operations for managing memory explicitly -- you can do your own memory management, you just have to do it in IO.
18:38 <centril> edwardk: but for a strict fp language
18:39 <edwardk> you can write in c++ with lambdas today in a strict language without gc
18:39 <centril> Cale: right 0)
18:39 ph88 joined
18:39 <edwardk> its awkward as hell and you have to be very careful about capturing references vs. values
18:39 <monochrom> What if you bothered? Answer: You would find that you would spend so much effort on escape analysis and the benchmark would not be much better than GHC.
18:39 <edwardk> so any other language you come up with will have to be very explicit about object lifetimes and ownership of data
18:40 _sras_ joined
18:40 <monochrom> Because you ought to look at what "heap allocation" looks like in GHC-generated code.
18:40 <centril> monochrom: im not interested for performance... im interested for real-timeness, i.e: GC pauses are a no-no in some applications
18:40 <_sras_> What sort of mixup can result in a "Failure to unify types" error?
18:40 <edwardk> centril: gc pauses aren't mandatory in gc'd languages.
18:40 <edwardk> there are realtime collectors
18:40 <monochrom> Ah OK.
18:40 <edwardk> ghc doesn't have one
18:41 <edwardk> but they are implementable
18:41 <centril> edwardk: ah, interesting!
18:41 <cocreature> _sras_: as the error message already says: your types don’t match up. if you provide some code, we might be able to help you more :)
18:41 <t7> >tfw unreadble code but it typechecks :/
18:41 <edwardk> you can write a fully concurrent collector along the lines of c4 in which the mutator and collector can proceed at the same time, gc's like metronome showed you can hit good realtime guarantees
18:42 <monochrom> Still, GHC has uprooted the conventional wisdom about heap-stack tradeoff. For GHC, stack is a heap object.
18:42 <edwardk> ghc isn't engineered that way, as it doesn't come without a cost
18:42 freechips joined
18:42 <edwardk> a c4 style gc requires a _read barrier_ and in a pure fp setting, reads far far outweigh writes
18:43 <centril> edwardk: btw... Rust =)
18:43 <_sras_> cocreature: But why does this message show instead of the usual "type does not match" error?
18:43 a3Dman joined
18:43 <edwardk> centril: rust exists. it doesn't solve any problem i actually have in practice, and has a turing complete type checker, but it exists, yes.
18:44 <nbro> is there a way to pass only one value to a data constructor which accepts only one? Reason: I need a second field as a support to the “public” field…
18:44 <cocreature> _sras_: probably because one of the types contains a type variable instead of a concrete type or something like that
18:44 <monochrom> Yikes read barrier. Why would anyone want that?!
18:44 <nbro> *which accepts two
18:44 ketas1 joined
18:44 <cocreature> nbro: what do you expect to happen in that case?
18:44 zero_byte joined
18:44 <centril> edwardk: I was referring to being explicit about object lifetimes - that is was Rust does
18:44 <edwardk> monochrom: i've got a sketch of a design for a haskell compiler that actually would exploit such a design, but its messy
18:44 <cocreature> you can partially apply data constructors but I think that’s not what you are trying to do
18:45 <monochrom> It's like "my program spends 90% of its time zeroing my memory buffers, so read barriers are OK!"
18:45 Enigmagic joined
18:45 bennofs joined
18:45 <Cale> centril: It's also worth noting that from the point of view of Haskell code, it's pretty much inappropriate to think of GHC's stack as a call stack.
18:46 <geekosaur> nbro, I think I need an example (I *think* you have a think in your problem description) but my fgirst guess is you want a smart constructor aka a function that does the actual construction
18:46 <Cale> It primarily consists of pattern matches waiting for their scrutinee to be sufficiently evaluated to match a pattern
18:46 <geekosaur> and then not export the data constructor
18:46 <edwardk> centril: yes, it has all sorts of ways to deal with loaning objects around to deal with nice disciplined stack-like usage. sadly the kinds of things you get with laziness tends not to follow such a structure, as evidenced by how jhc's region inference never worked out. so for haskell like code its kinda useless. and for c++-like code, i write enough of it
18:46 <edwardk> and manage my object lifetimes in a stylized enough manner than i literally never encounter the kinds of bugs rust is designed to prevent in my own code
18:46 <nbro> never mind
18:46 <centril> Cale: well, what about strict-only evaluation in haskell ?
18:46 <nbro> I think it wouldn’t work in all cases
18:46 <edwardk> so i'm left with no place to use rust. i can write c++ with a ton of notatonal baggage to fix a class of errors i don't experience
18:47 <nbro> ...
18:47 <Cale> centril: Well, that just adds yet more matches to functions.
18:47 <edwardk> with less useful templates which fix a class of errors and provide code reuse i _do_ use ;)
18:47 <Cale> centril: At some level, it's all turned into case expressions
18:48 <Cale> and those case expressions control the stack
18:48 <edwardk> monochrom: the self-healing read barrier stuff actually works out pretty well in terms of fixing up the asymptotics of concurrent gc, the problem with the write-barrier approach arises in pathological cases where the gc and the mutator keep tripping over each other
18:48 <geekosaur> centril, strict evaluation or no, haskell is still graph reduction not linear execution
18:49 takle joined
18:49 connrs joined
18:49 <centril> edwardk: you're a very smart guy & you are not everyone ;) memory unsafety is probably the #1 source of bugs when writing C & C++ for most applications
18:49 <Cale> Also, I strongly question the value of that extension -- it's usually going to be unhelpful imo.
18:50 <centril> Cale: what extension?
18:50 <ReinH> Cale: can we call it a graph reduction stack?
18:50 <Cale> centril: The one which strictifies everything
18:50 <monochrom> I just call it "stack".
18:50 <monochrom> Also it could be "call stack" but you have to change the meaning of "call".
18:51 <centril> Cale: oh that one... I haven't used it... If I care about RTS, I drop into Rust
18:51 <centril> Wel... I haven't done any non-university stuff with haskell yet, so...
18:52 <nbro> question: if have a data type defined with the record syntax, like data MyData = MyData {f1::String, f2::String}, apparently f1 and f2 are functions (as someone told me before)… what’s exactly the scope of this functions?
18:52 <geekosaur> same as any other function defined in that source file
18:52 <edwardk> centril: sure. lots of people pass stuff by reference and don't think about object lifetimes. i'm just careful to think of it as meaning the same thing as the sort of 'loan's i can do in rust and never claim ownership of passed pointers/references. instead requiring unique_ptr or shared_ptr discipline for anything that involves ownership transfer. modern
18:52 <edwardk> c++11+ encourages this pattern. valgrind, etc. are pretty darn good at catching when you violate it. the ecosystem there has had a long time to figure out how to live with its demons. ;)
18:53 <monochrom> Consider "case sin 5 of 0 -> ...". We gosub to the evaluation of sin 5, then return to continue the pattern matching. The case expression calls sin 5, then sin 5 finishes and returns to the case expression. The call stores how to return to the case expression. If you understand this sense of call, you can say "call stack".
18:53 <edwardk> centril: but lots of c/c++ is written by people who have no idea what they are doing
18:53 <nbro> geekosaur: ok, I thought they could be somehow special…
18:53 <geekosaur> in particular you control its export by its name, iirc the function is not exported with the constructor (but the *label* is, that is for use as part of the constructor instead of for retrieving the field value)
18:53 kosorith joined
18:53 <monochrom> But why overcommit yourself? Just say "stack". No one will misunderstand that you're dissuading from cabal. :)
18:54 Levex joined
18:54 <monochrom> Yikes, s/The call stores/The stack stores/
18:54 <geekosaur> you do need to keep the two separate, but an easy way to do that (sigh) is that labels are not first class --- they can only be used in specific circumstances and you can't replace them with bindings
18:54 <EvanR> bet you didnt know about this https://en.wikipedia.org/wiki/Metamonad
18:55 <geekosaur> example: record update syntax someRecord { label = value } -- the label must be literal and is not a function or etc.
18:55 insitu joined
18:55 <centril> edwardk: I'd say that concurrent imperative programs are complicated enough that it is very easy for even proficient C++ programmers to make mistakes... Just look at the flaws in Firefox that Rust just erases
18:55 ragepandemic joined
18:56 <monochrom> Yikes, termites eat metamonads.
18:56 <centril> who's idea was it to call it stack... yikes...
18:56 Rodya_ joined
18:56 sepp2k joined
18:57 <centril> one has to think of the googlability of names
18:57 <monochrom> Well it's probably inspired by the "full-stack developer" kind of "stack".
18:57 path[l] joined
18:57 <geekosaur> centril, nobody thought about that with c++. or c# for that matter
18:58 <ph88_> can anyone help with resolving the type ambiguity in this code? https://bpaste.net/show/d0a58220ed48
18:58 <srhb> centril: Try using Nix or NixOS.
18:58 <centril> haha... googleability is an actual word... https://en.wiktionary.org/wiki/googleability
18:58 <srhb> centril: No google can save you there...
18:58 <monochrom> Haha
18:58 <edwardk> Firefox has very complicated object lifetimes, complicated by almost-directly exposing their internals to javascript. A huge fraction of their complexity and leaks arise from the completely over-complicated clusterfuck that is xpcom that they use to glue everything together. For a project like firefox? Where you're mixing GC'd user controlled stuff and
18:58 <edwardk> random COM-like objects with awful reference counting? Replacing as much of that as humanly possible with something like rust? Huge win. Why? What it is replacing is a poorly thought out, overly engineered abomination.
18:58 PennyNeko joined
18:58 seveg joined
18:59 <centril> edwardk: forgot about XPCOM :p
18:59 <ReinH> (if you're really bad at reference counting, letting a computer do it for you is a big win)
19:00 <edwardk> centril: long long ago, i once wrote a web server that used the guts of the xpcom objects in firefox to do the content serving ;)
19:00 <srhb> Speaking about resources, tweag.io posed a blag on the linear types paper. http://blog.tweag.io/posts/2017-03-13-linear-types.html (in case that wasn't what spurred this discussion)
19:00 <edwardk> well, it was mozilla still at the time
19:00 <centril> srhb: it wasn't, it was sparked by a question regarding if and how GHC uses the stack
19:00 <edwardk> srhb: i'm somewhat dubious, just because of how many standard compiler optimizations linear types stomp all over.
19:00 contiver joined
19:01 <srhb> edwardk: I admit I haven't considered much how it interacts with things that aren't linearly typed. it seems exciting if it can be compartmentalized though.
19:01 <edwardk> srhb: but i'll happily be proven wrong by people deriving actual benefit from this stuff if it ever helps something
19:01 <lyxia> ph88_: "eot" does not occur in "Traversal' a Int"
19:01 <srhb> edwardk: Obviously the dream is noGC $ linearlyDo ... :-P
19:01 <edwardk> srhb: things like lambda lifting / lambda lowering mess with linearity
19:01 <MarcelineVQ> EvanR: I've no retortamonad for that
19:02 caumeslasal joined
19:02 <srhb> edwardk: Maybe the optimism is premature... :)
19:02 <edwardk> so far its basially a proof of concept showing that you could tweak some parts of the compiler to at least type check linearity, but there is no actual derived benefit in the compiled objects yet just that you can say things more directly this way.
19:03 <centril> this is the best thing about IRC - being handed awesome papers and talks
19:03 path[l] joined
19:03 <edwardk> if you want to just type check stuff with linear types for an edsl, etc. jeff polakow has a way of encoding a dsl with linear types and to get ghc to typecheck it, i think oleg et al have another way to encode it, etc.
19:03 <srhb> edwardk: But even without the potential allocation strategies, this could prove problematic for regular typing?
19:04 <edwardk> srhb: you can encode dsls with linear types today in haskell. the encoding is rather more baroque
19:04 <srhb> edwardk: Yes, I saw the Kiselyov in passing.
19:04 <edwardk> http://functorial.com/Embedding-a-Full-Linear-Lambda-Calculus-in-Haskell/linearlam.pdf
19:04 <srhb> I suppose the whole question is whether it integrates. if it does, it's pretty awesome, even without special allocation strategies.
19:05 <edwardk> that is jeff's version
19:05 marsam joined
19:05 <srhb> edwardk: Thanks!
19:05 dtornabene joined
19:05 <edwardk> i used something similar for a quantum computing EDSL i showed at a summer school a few years back
19:05 Miroboru joined
19:05 t0by joined
19:05 <edwardk> so i could ensure affine use of all my qubits
19:05 Cale joined
19:05 Swizec joined
19:06 Luke joined
19:06 <srhb> Related to Quipper?
19:06 <edwardk> made it nice and easy to ensure i had unitary operators
19:06 takle joined
19:06 <edwardk> mine was more an exercise in showing off finally tagless encodings and how to build edsls out of things like free and codensity
19:06 Rodya_ joined
19:06 <* srhb> nods
19:07 <edwardk> since at the time we didn't know about reflection without remorse
19:07 <edwardk> and codensity was the one hammer i had to fix up the asymptotics of free
19:07 merijn joined
19:07 <srhb> When all you've got is a codensity comonad, every problem looks like ???
19:08 <monochrom> a potential victim of the continuation passing style :)
19:08 <srhb> :-)
19:08 thibaud_ joined
19:09 <edwardk> https://github.com/ekmett/dsl2011/blob/master/VectorSpace.hs i think was the demo edsl without linearity, then we did an exercise during the class of building up a lib in the oleg/ken style.
19:09 darjeeling_ joined
19:09 <edwardk> it was a 3 day workshop.
19:09 <edwardk> this was one of a dozen or so examples
19:10 <edwardk> https://github.com/ekmett/dsl2011/blob/master/QM.hs is one artifact i had lyng around. i don't remember if its what we started the finally tagless form with, or what we ended the session with
19:10 <nitrix> srhb: a hammer.
19:11 <ReinH> srhb: I believe you are looking for "Kan extension".
19:12 <shapr> I filed one of those on my taxes, and it make the IRS cry.
19:12 <ph88> lyxia, good tip thx, i will continue fixing some more errors
19:13 Rodya_ joined
19:13 <srhb> edwardk: I can't even imagine going through that even in a 3 day workshop. I think I need to reread the papers. :)
19:14 <edwardk> srhb: i'm a grueling taskmaster =)
19:14 chaptastic joined
19:14 <srhb> edwardk: Ah, then it's a piece of cake ;-)
19:14 <ystael> shapr: bahaha
19:18 <Zemyla> Hmm, edwardk, a question about your adjunctions package.
19:19 marsam joined
19:19 <edwardk> Zemyla: shoot
19:20 Thra11 joined
19:21 mou joined
19:21 <Zemyla> Would including something along the lines of liftEqRep :: (Traversable f, Representable f) => (a -> b -> Bool) -> f a -> f b -> Bool, and similarly for liftCompareRep, be useful?
19:22 <Zemyla> Actually, those just need Foldable, not Traversable.
19:23 <freeside> IHNJ,IJLS "Grothendieck bifibration"
19:24 tomphp joined
19:24 <shapr> freeside: what's the IHNJ and IJLS? My first thought was myers-briggs, but that's not it.
19:24 amf joined
19:25 <freeside> i have no joke, i just like saying
19:25 ptvirgo joined
19:25 AppAraat joined
19:26 <amf> is there any way to use applicative style with a data types record fields? i have a rather large structure and id like to use the record names as hints
19:26 <Zemyla> liftEqRep :: (Foldable f, Representable f) => (a -> b -> Bool) -> f a -> f b -> Bool; liftEqRep eq = \fa fb -> foldr (&&) True $ mzipWithRep eq fa fb
19:27 <AppAraat> hello, I'm trying to run a little Haskell program but I have no idea where to start. I downloaded it here - https://github.com/tensor5/flAccurateRip - and I tried doing "ghc -o flaccurate Setup.hs" but it doesn't seem to accept any input.
19:28 <freeside> amf: https://ocharles.org.uk/blog/posts/2014-12-04-record-wildcards.html ?
19:28 <amf> AppAraat: cabal sandbox init && cabal install
19:28 <shapr> amf: already familiar with lenses?
19:28 sigrlami joined
19:29 <Zemyla> liftCompareRep :: (Foldable f, Representable f) => (a -> b -> Ordering) -> f a -> f b -> Ordering; liftCompareRep cmp = let { cmbC EQ b = b; cmbC a _ = a } in \fa fb -> foldr cmbC EQ $ mzipWithRep cmp fa fb
19:29 <AppAraat> amf: cabal: unrecognised command: sandbox (try --help)
19:29 <amf> shapr: somewhat...
19:30 <amf> AppAraat: likely on an old version of cabal. download stack ( haskellstack.org ) and do "stack init"
19:31 <Zemyla> Also, edwardk, pureRep could probably be changed to pureRep :: (Distributive f) => a -> f a; pureRep a = fmap getConst $ distribute $ Const a
19:31 sea_wulf joined
19:31 Fairy joined
19:31 <shapr> amf: I use lens to easily grab fields from records: https://hackage.haskell.org/package/lens-tutorial-1.0.2/docs/Control-Lens-Tutorial.html and https://github.com/shapr/tmuxmarta/blob/master/src/Lib.hs
19:31 chaptastic joined
19:31 <AppAraat> amf: ok I'll try that, thanks.
19:32 <sigrlami> hey folks, I'm using yesod and yesod-job-queue library that exposes only simple context (MonadBaseControl IO m, MonadIO m), how can I add MonadLogger without chaning library? I want to use logInfo, logError inside jobs
19:32 govg joined
19:32 structuralist joined
19:33 <shapr> amf: does my answer relate to your question at all? :-)
19:34 <amf> shapr: not really... i want something like: Blah <$> _someField = whatever <*> _otherField = pure Nothing
19:34 <edwardk> Zemyla: the pureRep thing is cute. the Foldable bit may be a bit underdetermined, as Foldable doesn't guarantee it hits all the 'a's in the structure, technically
19:34 <edwardk> Zemyla: sorry that reply took so long . real life is intervening
19:35 <Zemyla> edwardk: Requiring Traversable would, though.
19:35 <nbro> lol, implemented correctly a “render” function for a GapBuffer using the two buffers style at the first attempt
19:35 <nbro> render :: GapBuffer -> String
19:35 <nbro> render GapBuffer {before = [], after=val} = val
19:35 <freeside> yay you did it
19:35 <nbro> render b = render GapBuffer {before=tail (before b), after=head (before b) : after b }
19:35 <nbro> loooool
19:35 agjacome joined
19:35 <shapr> amf: you're constructing Blah with values from a record?
19:35 curious_corn joined
19:35 <edwardk> Zemyla: yeah traversable is definitely sound
19:36 <edwardk> nbro: keep in mind the before buffer should be reversed
19:36 <edwardk> so its more like render (GapBuffer as bs) = reverse as ++ bs
19:36 <nbro> edwardk: it is indeed
19:36 <nbro> the way I implemented
19:36 <nbro> it
19:36 <ph88> i have 3 errors here and i don't understand any of them, could someone take a look ? https://bpaste.net/show/1166c0594a67
19:37 <amf> shapr: no, i want to label the positions so its clear what is being used
19:37 <nbro> edwardk: for example, a moveLeftCursor function looks like this: moveLeft b = if atStart b || atEnd b then b else GapBuffer {before = head (after b) : before b, after = tail (after b)}
19:38 Prutheus joined
19:38 <edwardk> why does moving left have a problem with being at the end?
19:38 <edwardk> it should just be one or the other
19:39 twanvl joined
19:39 <nbro> edwardk: I don’t want it to give an error, but just to return the GapBuffer unchanged if the second list is empty, since you would not be able to move left anymore
19:40 <edwardk> foo (GapBuffer (f:fs) bs) = GapBuffer fs (f:bs); foo g = g -- moves 'backwards'
19:40 <edwardk> foo (GapBuffer fs (b:bs)) = GapBuffer (b:fs) bs; foo g = g -- moves 'forwards'
19:41 boojinks joined
19:41 fresheyeball joined
19:41 <edwardk> the foo g = g handles the 'already at start' case for moving backwards, and the already at end case for moving forward
19:42 <nbro> if you have a GapBuffer like this GapBuffer {before=“”, after=“”}, if I didn’t have the check atEnd b (which in this case returns also true), I would do some tails or heads on empty lists
19:42 Miroboru joined
19:43 <edwardk> shouldn't
19:43 <edwardk> ee the thing i showed above?
19:43 <edwardk> it only took the head off of f:fs, then consed onto bs
19:43 <edwardk> only one list got 'head/tail'ed or pattern matched in this case
19:43 <edwardk> the other is only ever consed onto
19:43 <edwardk> check your logic
19:43 <edwardk> consing onto an empty list is safe
19:44 <edwardk> gotta go
19:44 <nbro> ok, I will save this conversation and I will check later, because now I have to leave … :D
19:44 <nbro> edwardk: thanks again!
19:45 <shapr> amf: did you look at freeside's suggest of record wildcards?
19:45 marfoldi joined
19:48 balor joined
19:50 <zcourts> Any got (and willing to share) or know of a script available that can parse the output of ghc --show-packages - I'm linking to GHC, including Haskell in a C++ app using cmake to find GHC and its libraries but can't suss the best way to do it. Found the --show-packages arg which seems to have all the info.
19:50 wraithm joined
19:51 <ph88> zcourts, sounds like a cool project !
19:51 <geekosaur> zcourts, I think you want to look at ghc-pkg
19:51 <amf> i did... not what im after.. im fairly certain its not possible, which is fine
19:52 Levex joined
19:52 <zcourts> ph88: It is! Having lots of fun wit this
19:52 <geekosaur> ghc-pkg list --simple-output --names-only
19:52 <zcourts> geekosaur: thanks, I'll have a look at that
19:52 <ph88> zcourts, why you use c++ too ?
19:52 <geekosaur> actually I think you just want ghc-pkg dump
19:52 <geekosaur> which should give you easily parsed output
19:52 acfoltzer joined
19:53 <geekosaur> fsvo easily parsed...
19:53 <zcourts> awesome, thanks geekosaur
19:53 <geekosaur> actually it's not that bad to parse, certainly easier than what the ghc version vomited agt me
19:53 <geekosaur> eitjher one string on the same line as the key, or an indented list without commas etc. following
19:54 darjeeling_ joined
19:54 <zcourts> ph88 huge code base already in C++. Using Haskell DSL and want "Sparks"
19:54 <ph88> Sparks ?
19:55 <zcourts> geekosaur: looks more manageable. Thanks
19:55 bjz_ joined
19:56 <zcourts> ph88 forkIO basically
19:58 insitu joined
19:58 cdg joined
19:58 eatman joined
19:59 ptvirgo joined
20:02 dysoco joined
20:04 chlong joined
20:05 darjeeling_ joined
20:05 AppAraat left
20:06 <sphinxo> How can I use nest from https://hackage.haskell.org/package/ansi-wl-pprint- with parens to do http://lpaste.net/6147885718719954944
20:06 <sphinxo> ( the latter one )
20:06 Cale joined
20:07 <sphinxo> oh and the <+> is mean't to be <$>
20:08 mrcrjs_ joined
20:09 meoblast001 joined
20:10 faberbrain joined
20:10 Ageoffire joined
20:12 Perspicaciosity joined
20:15 freechips joined
20:16 zcourts joined
20:17 chaptastic joined
20:17 sssilver joined
20:18 ner0x652 joined
20:19 contiver joined
20:20 <mbw> Earlier today I noticed a slowdown when defining a Monoid via Semigroup (GHC 8.0.1/2) compared to just Monoid. geekosaur noted that Semigroup probably hasn't been given appropriate pragmas yet, since it's a fairly new addition to base, and that the situation might improve with GHC 8.2. Still, how could I confirm that this is a problem already recognized by GHC devs? Would there be a corresponding bug ticket,
20:20 <mbw> or is there another page dedicated to this kinda stuff?
20:20 augur joined
20:20 curious_corn joined
20:21 <Cale> mbw: What kind of slowdown do you mean? How did you write the Monoid instance?
20:21 <heArtbreakers> My batt 3% only
20:21 louispan joined
20:21 MrWoohoo joined
20:21 <Cale> Which pragmas was geekosaur talking about?
20:22 ragepandemic joined
20:24 <sphinxo> given [a,b,c...] how can I do a <$> b <$> c
20:24 <sphinxo> fold?
20:24 <Cale> sphinxo: How do you expect that to typecheck?
20:24 <heArtbreakers> Using zelbra
20:25 <sphinxo> bad example, for a list of the same type
20:25 <Cale> But yeah, that kind of thing would be a foldr or foldl depending on the way you'd like the association to go
20:25 <heArtbreakers> Cya later
20:25 <Cale> (and if you want foldl, probably you really want foldl')
20:25 <mbw> Cale: Ok, I scrolled back and he was referring to RULES. I'll paste the example I was running.
20:26 <Cale> I was unaware of any RULES for Monoid to begin with
20:27 <Cale> mbw: It's possible that something is preventing your instance from inlining
20:27 <Cale> But yeah, paste it and let's take a look
20:29 <ph88> could someone take a look at this paste https://bpaste.net/show/1166c0594a67 ?? on those errors i get a mismatch on actual type and expected type, but i don't understand why those types are expected
20:29 <Cale> "Actual type: f this" lol
20:30 <ph88> lolol
20:30 <ph88> hadn't seen that one yet xD
20:30 anton joined
20:30 <Cale> Well, unfold the definition of Traversal' if you want to make any sense of this
20:31 <ph88> what do you mean unfold ?
20:31 connrs joined
20:31 <Cale> type Traversal' s a = Traversal s s a a
20:31 <Cale> type Traversal s t a b = forall f. Applicative f => (a -> f b) -> s -> f t
20:32 <Cale> We're attempting to write an instance for EotTerminal (Either this next)
20:32 subttle joined
20:32 <Cale> class EotTerminal eot where
20:32 <Cale> eotTerminal :: Traversal' eot Int
20:32 <Cale> So eotTerminal :: Traversal eot eot Int Int
20:33 <unclechu> hey guys, can i force `hlint` to read `default-extensions` from *.cabal file?
20:33 <Cale> and eotTerminal :: forall f. (Int -> f Int) -> eot -> f eot
20:33 <Cale> and in this case, eot = Either this next
20:33 <unclechu> it shows me irrelevant parsing errors because some of extensions specified as `default-extensions` in cabal-file
20:33 JuanMiguel joined
20:34 <Cale> So the type of eotTerminal in the instance is eotTerminal :: forall f. (Int -> f Int) -> Either this next -> f (Either this next)
20:34 <ph88> oh that's what you mean with unfold is go from TH to normal haskell ?
20:34 <ph88> Traversal' is TH right ?
20:34 <Cale> There's no TH here
20:34 <ph88> oh
20:35 <Cale> That's just a type synonym
20:35 <Cale> unclechu: My solution to this is just to never ever use default-extensions
20:35 <Cale> unclechu: This has a lot of other benefits
20:35 <mbw> ok here it is: http://lpaste.net/954950385871618048
20:36 <ph88> Cale, i'm not sure which type i would want here
20:36 <mbw> This is the version using Semigroup, which is eliminated easily, if you want to compare it with Monoid-only-performance.
20:37 Heasummn joined
20:37 <Cale> mbw: btw, -O3 is out of range -O2 is the highest optimisation level
20:37 <Cale> (it will fix that for you though -- at one point it used to just ignore the flag)
20:37 <mbw> Yeah I thought so, too, however someone suggested I better use it :/
20:37 <kuribas> I found it does more optimizations with -O2
20:37 <mbw> But I did try it with -O2 as well, for the record.
20:37 <ph88> Cale, in other words, i'm not sure if i should change the actual type or change the expectation of the type
20:38 <erisco> I was being jocular
20:38 <Cale> ph88: You probably want Left <$> eotTerminal f fields
20:38 <mbw> k, my bad
20:39 GJL joined
20:39 steshaw joined
20:39 <ph88> Cale, ok i believe you but how do you get this idea ?
20:39 Luke joined
20:39 <Cale> ph88: Well, what's the type of eotTerminal f fields?
20:39 <Cale> (if you don't know, the compiler error tells you)
20:40 <Cale> (but you should probably think it through for yourself)
20:40 <ph88> f this lol
20:40 <Cale> right
20:40 <Cale> and you want something of type f (Either this next) right?
20:40 <Cale> So that suggests that we ought to fmap Left over what you've got there
20:40 curious_corn joined
20:41 <Cale> at least, that's the most obvious thing to do
20:41 <ph88> where you say "right?" i wasn't sure about that either, so that's why i was asking where you get that idea (it's probably right though)
20:41 <ph88> ok i guess it aint that obvious to me
20:41 tag joined
20:42 <ph88> that still leaves the last error of line 128
20:42 <Cale> ph88: Well, if I gave you something of type A, and asked you to give me something of type Either A B, you would probably guess to apply Left, yeah?
20:42 <Cale> mbw: I'll try some stuff in a moment, but maybe try adding {-# INLINEABLE ... #-} pragmas to the method implementations in your instances
20:43 <Cale> Er, or should it be {-# INLINE ... #-} ?
20:43 <Cale> I dunno
20:43 <ph88> yeah ok, i guess it flows naturally from the given type of eot
20:44 xkapastel joined
20:44 <mbw> Me neither, I don't have that much experience with pragma-pased optimization yet.
20:44 marsam joined
20:44 <ph88> Couldn't match type ‘f’ with ‘(->) ()’ is that second thing a function that takes an argument and returns void ?
20:44 <Cale> https://downloads.haskell.org/~ghc/latest/docs/html/libraries/base- -- see here for an example
20:44 <mbw> ok
20:44 <mbw> Let's do this!
20:45 <Cale> ph88: That second thing is (->) partially applied to ()
20:45 <ph88> oh is this a type level thing ?
20:45 <Cale> Yeah
20:45 takuan joined
20:45 Levex joined
20:46 ramzifu joined
20:46 darjeeling_ joined
20:46 <Cale> I don't know where you're getting that, so I can't tell you why it's telling you that, but it looks like maybe you're giving an additional argument of type () to something
20:46 <dolio> Cale, mbw: `mappend = (<>)` can't inline, it isn't saturated.
20:46 <ph88> so instead of id i probably need some lens thing ?
20:46 zerokarmaleft joined
20:46 <dolio> (<>) can't inline, that is.
20:46 <mbw> Ok, adding INLINE to everything makes it fast.
20:47 <mbw> To all instance implementations, that is.
20:47 merijn joined
20:47 <Cale> nice, but see also dolio's comment
20:47 <dolio> Known calls to `mappend` could inline into `(<>)`.
20:47 <mbw> The warnings about MonoidSum/SemigroupSum not being specializable persist.
20:47 Volt_ joined
20:47 <ph88> Cale, what do you mean "i don't know where you're getting that", what's that? The inspiration of the code i'm trying to fix is right about it in code piece 1 and code piece 2
20:47 <Cale> ph88: I mean, that specific type error
20:48 <ph88> it's in line 58 of the paste
20:48 <ph88> i put line numbers near the code
20:48 <mbw> dolio: What does "not saturated" mean?
20:48 <ph88> but the line numbers of the paste don't line up with the line numbers of the error message
20:48 <Cale> mbw: Not applied to as many arguments as it could be
20:49 <Cale> ph88: oh, I see
20:49 <mbw> In the sense of being used in a curried context?
20:50 <Cale> ph88: Well, again, what's the type of eotTerminal supposed to be here?
20:51 redmq joined
20:51 <ph88> Cale, i think still the same type as you told me before eotTerminal :: forall f. (Int -> f Int) -> eot -> f eot where eot is Either this next
20:51 <Cale> nope, eot is something else now
20:51 <Cale> eot is ()
20:51 <Cale> So it's forall f. (Int -> f Int) -> () -> f ()
20:51 <Cale> right?
20:51 <ph88> ye
20:51 GJL joined
20:51 <ph88> so maybe f <$> () ?
20:51 <ph88> i will try it
20:52 zcourts joined
20:52 <ph88> hhmm no Actual type: f (f Int)
20:53 <ph88> this Int is not good
20:53 <ph88> here eotTerminal :: forall f. (Int -> f Int) -> eot -> f eot Int needs to change to something else i think
20:53 <Cale> Well, there are some things you could do. A simple one would just be to produce the empty traversal and have the right hand side be pure ()
20:53 coot joined
20:53 <ph88> i was trying to make a type hole but i couldn't do it on a class
20:54 <Cale> The question is, what Int values does () have in it?
20:54 <ph88> ok it compiles now, but i'm pretty sure that Int i put there is nonsense
20:54 <Cale> Might be.
20:54 <Cale> I have no idea what the intention of the code is
20:55 <ph88> it's a library to work with GHC.Generics combined with Lens traversal
20:55 <ph88> i think () is suppose to denote the end of the data constructor fields
20:56 path[l] joined
20:56 <ph88> if i wouldn't be generating Ints, but a list instead then in that spot i should put the empty list
20:56 <ph88> or with Ints maybe a 0
20:56 <ph88> eh i forgot the word for it, something about monoids, 1 sec
20:56 contiver joined
20:56 curious_corn joined
20:56 <ph88> mempty
20:56 <ph88> ye
20:57 <Cale> You certainly could do something like eotTerminal f () = () <$ f 0
20:57 <ph88> i was using this eot code before on a pretty printer so i put there P.empty for the empty Doc
20:57 <Cale> Probably unhelpful though -- not a very good traversal that
20:57 pleax joined
20:58 <ph88> maybe this type signature eotTerminal :: Traversal' eot Int should change to eotTerminal :: Traversal' eot eot
20:58 <ph88> because i don't want Int .. i just put Int there because i couldn't make a type hole
20:58 <Cale> I don't understand what you mean by type hole there.
20:58 <ph88> _
20:59 <Cale> You want the compiler to decide for you what type your class method should have in general?
20:59 <ph88> sometimes i put that in function signatures and GHC infers the type
20:59 <merijn> ph88: Type hole as in PartialTypeSignatures, or typed hole?
20:59 <ph88> i tried to put _ there to let the compiler throw an error and tell me what the expected type should be, so i can put the correct type there
20:59 <Cale> Yeah, that's not going to fly -- you really need to figure out what it is that you want. :)
21:00 <ph88> how can i find out ?
21:00 <Cale> Well, you can find out by starting with code that doesn't involve type classes at all
21:00 <Cale> and abstracting over an actual pattern that has come up
21:01 <ph88> the tutorial says i must use type classes
21:01 <Cale> w... which tutorial is this?
21:01 <ph88> there is one serialization example and one deserialization example https://generics-eot.readthedocs.io/en/latest/tutorial.html
21:01 Gurkenglas joined
21:02 redmq joined
21:02 darjeeling_ joined
21:02 <ph88> i don't need to go to Int's .. i'm just trying to make a generic function that can be used with Lens for traversing
21:02 moth joined
21:02 <dolio> mbw: Your definition of `(<>)` had two arguments to the left of the =, but your use in `mappend` had 0.
21:03 <Cale> Well, traversing fields of *what type*?
21:03 Prutheus joined
21:04 louispan joined
21:04 <ph88> Cale, lots of types https://bpaste.net/show/2576c10d7cf4 that's why i use GHC.Generics so i can traverse on the Rep resentation
21:05 <ph88> i can use fromEot and toEot
21:06 <mbw> dolio: So it would make a difference if I wrote mappend x y = (<>) x y?
21:06 fuzzy_id joined
21:06 AleXoundOS joined
21:06 <mbw> Also, -ddump-inlinings seems to suggest that mappend and (<>) were inlined, but maybe I am reading that wrong.
21:07 <ph88> fromEot :: (Rep a ~ M1 D c f, EotLib.HasConstructorsG f, Datatype c, Generic a, generics-eot- f) => EotLib.EotG (Rep a) -> a
21:07 <ph88> i think i will be traversing on the Rep a
21:07 conal joined
21:07 <ph88> EotLib.EotG (Rep a) i mean
21:07 <dolio> mbw: Yes, it would make a difference with respect to the definition of (<>) getting inlined into the definition of mappend.
21:09 <dolio> In your example it might not matter, because `mappend` might get inlined to `(<>)` which is saturated and can itself inline.
21:10 <dolio> The former would be the difference between defining things directly in Monoid vs. Semigroup, though.
21:10 Thra11 joined
21:10 <mbw> This all seems very finicky.
21:10 obadz joined
21:11 argent0 joined
21:12 curious_corn joined
21:12 <fuzzy_id> heya, i want to do a version bump in haproxy from 1.7.2 to 1.7.3. shall i do commits and pull requests on the master branch?
21:12 <ReinH> GHC optimizations can be finicky.
21:12 <fuzzy_id> the nix manual says to avoid working on it…
21:13 nilof joined
21:14 Koterpillar joined
21:14 <mbw> Still, a structured approach must be possible. From a productivity perspective (i.e. before resorting to reading Core/asm), which dump files are the most conlusive and should be checked first?
21:14 <ReinH> fuzzy_id: is... that a Haskell question?
21:15 cads joined
21:15 <mbw> After all, profiling output only gives you a naughty list...
21:16 <fuzzy_id> ah, sorry!
21:16 <fuzzy_id> wrong channel
21:17 merijn joined
21:18 structuralist joined
21:18 <nilof> Question: I'm trying to make a Heap typeclass with a default instance of monofoldable, but the compiler complains about overlapping instances even for things which are not heaps
21:18 <nilof> Here's ny current conde
21:18 <nilof> http://lpaste.net/353502
21:18 hereForMatrices joined
21:18 <merijn> nilof: Honestly, heaps don't sound like a good candidate for a typeclass
21:18 <mauke> there's no such thing as a default instance
21:20 <hereForMatrices> hi, I'm messing around with a matrix I've defined, newtype Matrix a = Mat ((Int, Int), (Int, Int) -> a) and had questions about a function I'm trying to apply. I don't understand why it's not working.
21:21 Luke joined
21:21 <nilof> I can implement a heap typeclass just fine, and Okasaki does it as well in his book, I just want to define an instance of monofoldable
21:21 BlueRavenGT joined
21:21 <nilof> without having to duplicate my code for every different kind of heap
21:22 jaspervdj joined
21:24 <sphinxo> How can I make happy show what it has parsed so far, when it errors?
21:24 <nilof> the code itself works fine, but the MonoFoldable instance messes with other code that uses MonoFoldable
21:25 tomphp joined
21:26 <mbw> hereForMatrices: People would quite possibly be able to help you with your actual questions... You can post some sample code here: http://lpaste.net/new/haskell
21:26 uglyfigurine joined
21:26 freeside joined
21:27 <hereForMatrices> Thanks mbw, I'm pasting it now
21:28 <merijn> nilof: Well yes, what you want isn't really possible
21:28 <lpaste_> HereForMatrices pasted “matrix ” at http://lpaste.net/353503
21:28 shayan_ joined
21:29 <hereForMatrices> Oh cool, there's a bot! I keep getting errors regarding the where on the pointwiseApply function
21:29 <merijn> hereForMatrices: Could you lpaste the errors too? :p
21:30 <Koterpillar> hereForMatrices: what are the types of r1 and r2?
21:30 <hereForMatrices> r1 and r2 should both be of type a
21:30 <merijn> hereForMatrices: Oh, actually I already see the error
21:30 <merijn> hereForMatrices: Line 16 and 19
21:30 <lpaste_> HereForMatrices revised “matrix ”: “matrix ” at http://lpaste.net/353503
21:30 rcat joined
21:30 <merijn> :t '+'
21:30 <lambdabot> Char
21:30 <merijn> Char is not a function
21:31 <Koterpillar> hereForMatrices: they are not
21:31 <freeside> i am not a function. i am a FREE MAN!
21:31 <merijn> hereForMatrices: Presumably you meant (+)?
21:31 <merijn> :t (+)
21:31 <Koterpillar> hereForMatrices: in Mat ((x1, y1), r2), r2 :: (Int, Int) -> a
21:31 <lambdabot> Num a => a -> a -> a
21:31 <hereForMatrices> Wait, Koterpillar, I'm not sure I understand
21:31 <sphinxo> any guides on debugging happy parsers?
21:32 <nilof> What if I use template Haskell? If I declare instances for concrete types the code will always be the same, the only difference is that the Argument "Heap h" at the top would be replaced with "LeftistHeap h", "BinomialHeap h", etc
21:32 <Koterpillar> hereForMatrices: (Mat((x,y), r1))
21:32 <Koterpillar> hereForMatrices: what is the type of r1?
21:32 <merijn> nilof: I would start of first questioning why Heap is a typeclass, rather than a datatype
21:32 path[l]_ joined
21:33 <nilof> Because it abstracts over different types of heaps, and can have many different implementations
21:34 <lpaste_> HereForMatrices revised “matrix ”: “matrix ” at http://lpaste.net/353503
21:34 <hereForMatrices> the error I'm unsure how to understand or interpret - which is why I don't know how to answer your question Kot - is the one related to line 12
21:34 <hereForMatrices> the where in the pointwiseApply function
21:34 <Koterpillar> hereForMatrices: this is precisely what I'm trying to explain
21:35 <merijn> hereForMatrices: 'r2 :: (Int, Int) -> a'
21:35 <merijn> hereForMatrices: But you're applying r1 to it
21:35 <merijn> And 'r1 :: (Int, Int) -> a' too
21:35 <Koterpillar> hereForMatrices: r1 and r2 are both functions from coordinates to values
21:35 <merijn> So that doesn't typecheck
21:35 <hereForMatrices> Ohhhhhhhh
21:35 <hereForMatrices> ohh
21:35 <hereForMatrices> oh
21:35 <Koterpillar> hereForMatrices: so you can't apply r1 to r2, nor op to any of them
21:36 rcat joined
21:36 <nilof> That and Okasaki implements a heap typeclass in the Haskell code appendix of his purely functional data structures book
21:37 <merijn> nilof: I'm not saying you can't, I'm just saying it's not a great idea, as that kinda use of typeclasses generally doesn't do what you want as well as you'd hope. As evidenced by the imposibility of writing a "default" monofoldable
21:38 <mbw> hereForMatrix: Are you using an editor setup that lets you see things like hlint and ghc-mod? I found these kind of tools quite helpful when starting out. Also being able to inspect the types, either in your editor, or ghci, is helpful when writing polymorphic code.
21:39 <hereForMatrices> no, I've just been on notepad++
21:39 <hereForMatrices> I'll look at hlint though
21:39 <maerwald> I find hlint highly useless, most of the suggestions are odd and opinionated
21:40 <maerwald> when it comes to pointfree vs pointful style, it assumes those things are the same, which they are not
21:40 rstefanic joined
21:40 <mbw> hlint is more for "best practices", like obvious simplifications. However, in my vim setup I find it very helpful to auto-expand pattern matches, insert types etc. But many of those "fancy things" are of course a matter of taste.
21:40 <nilof> But I can see myself wanting to do something similar for a lot of problems, like making a default applicative instance for all monads
21:41 <hereForMatrices> yeah, I generally find those things helpful
21:41 marsam joined
21:41 <hereForMatrices> I'm just on spring break, and figured I'd mess around, I found problems from an old lecturer at the college I go to, and I've been working through them
21:42 <hereForMatrices> would changing the where to this, resolve the issue?
21:42 <hereForMatrices> where f (Mat((x1, r1)) (Mat(x2, r2)) = (Mat ((x,y), (op ((r1 x1) (r2 x2)))))
21:42 <hereForMatrices> that way, x1, and x2 are the tuples, and r1 and r2 are the functions which get applied to that tuple
21:42 <merijn> hereForMatrices: I would assume x1 and x2 are sizes?
21:43 <Koterpillar> hereForMatrices: it won't anyway, you need a _function_ as the last element
21:43 desktop joined
21:44 <Koterpillar> hereForMatrices: [hint] maybe start writing it like Mat ((_, _), \(x, y) -> _)
21:44 tfc joined
21:45 <hereForMatrices> thank you for the help Koterpillar, I'm going to try that, and some other thigns
21:45 <hereForMatrices> things*
21:45 <freeside> good luck
21:46 <freeside> if you give up, http://lpaste.net/353507 has the answer
21:46 rkazak_ joined
21:47 tfc joined
21:47 <Koterpillar> freeside: well, if you go there, why not just make Matrix an instance?
21:47 <freeside> i don't know! i didn't think about it. i did it on autopilot.
21:47 chlong joined
21:48 TheEpsylon- joined
21:48 <freeside> it compiles. ship it!
21:48 Prutheus joined
21:49 hydraz joined
21:49 Lord_of_Life joined
21:50 zdenal joined
21:50 systadmin joined
21:52 chaptastic joined
21:52 path[l] joined
21:52 hiratara joined
21:53 seveg joined
21:56 conal joined
21:57 marcopullo joined
21:57 markani joined
21:57 <markani> is this the general help channel?
21:57 <freeside> no, that would be lmgtfy.com
21:58 <kadoban> markani: For haskell, yes
21:58 rcat joined
21:58 markani left
21:58 <Koterpillar> this is the general channel for the Haskell programming language
21:59 <freeside> you ask one question, you get three answers.
21:59 <freeside> satisfaction guaranteed or your money back!
21:59 <ongy> they left already
22:00 <freeside> and we don't even care if you stick around to hear them!
22:00 <hereForMatrices> Well, I didn't get it to compile, and after seeing the solution freeside, I hadn't seen the $ or * used outside of learn you a haskell, and I never messed with them
22:00 <freeside> yeah, the applicative thing is super mindblowing
22:01 <Squarism> So does haddock require all exposed modules to have documentation?
22:01 <freeside> this might help: https://twitter.com/mengwong/status/841408199332880384
22:01 <Koterpillar> hereForMatrices: warning: <$> is not $, and <*> is not *
22:02 tomphp joined
22:02 <lyxia> Squarism: it's not required, just strongly recommended
22:02 <jle`> haddock really doesn't require anything
22:03 <mbw> hereForMatrices: https://github.com/bitemyapp/learnhaskell also has a nice collection of materials, next to the Wiki and the other usual places.
22:03 <Squarism> ....As i need my testsuite to have access to big parts of the codebase i exposed most of it. And now haddock wants dock for stuff i dont even planned on exposing
22:03 <freeside> i'm guessing that what you want with the pointwiseAppply is to run both r1 and r2 on the new matrix (which just so happens to be the first matrix), and combine the result using whatever operator was specified by add/sub?
22:03 <jle`> Squarism: haddock will warn you about undocumented unexposed modules
22:03 <jle`> but i'm pretty sure it doesn't require them to be documented
22:04 preyalone joined
22:04 <freeside> as you can see from my tweet, the X <$> Y <*> Z magic will run both Y and Z on the input, and then run X on the result, which seems like what you want
22:04 alexbiehl joined
22:05 <kuribas> The reader monad is the most abused monad...
22:05 <kuribas> it's obfuscation device #1
22:05 greeny joined
22:05 <freeside> haskellbook.com's chapter on Reader does a very patient job working you through it
22:05 dario` joined
22:06 <jle`> indeed Reader has few actual real purposes outside of pedagogy
22:06 LeCamarade joined
22:06 <Squarism> jle`, lyxia : This is my output running "stack build --haddock" : http://lpaste.net/353508
22:06 <Squarism> looks like it fails?!
22:06 <jle`> it's useful for teaching but there aren't really many situations where it is the most effective tool
22:06 <Squarism> ...because of missing
22:06 <Squarism> docs
22:07 <geekosaur> re earlier: the RULES wouldn''t be on Monoid /per se/ but on things like folds
22:07 vtomole joined
22:07 <jle`> Squarism: i hvaen't seen that beore, but i suspect that it doesn't have to do with missing docs
22:07 <jle`> it's just a coincidence that the error happens right after the warnings for missing headers
22:08 louispan joined
22:08 <jle`> that's my guess, at least
22:08 <merijn> jle`: I kinda like Reader...
22:08 <jle`> who doesn't like reader, it's so cute
22:08 <merijn> jle`: Or did you mean as opposed to ReaderT?
22:08 <jle`> as opposed to ReaderT, yes
22:08 <lyxia> Squarism: parse error on input ‘-- | GameStarted’
22:08 <jle`> ReaderT is pretty useful :)
22:09 <* geekosaur> back from store, will likely be unstable for the next hour :/ wheeeeeee...
22:09 <sphinxo> Hi, is anyone here good at spotting the sources of happy shift/reduce conflicts?
22:09 <freeside> "but Reader is just a ReaderT wrapped around an Identity monad" (sung to the melody of "but a monad is just a monoid in the category of endofunctors")
22:09 <Squarism> lyxia, good catch!
22:09 <Squarism> thanks
22:09 Habib_ left
22:09 <jle`> s/wrapped around an/applied to
22:10 <jle`> but yeah
22:10 balor joined
22:10 <lyxia> sphinxo: have you tried looking at the output of happy -i
22:11 <sphinxo> yes, and I see which state it is
22:11 <geekosaur> actually I find happy's version of that much worse than AT&T yacc's
22:11 <freeside> nodnod
22:11 asmyers joined
22:11 <sphinxo> http://lpaste.net/8643826338391654400 is the output, state 97 is the one I need to fix
22:12 faberbrain joined
22:12 structuralist joined
22:12 <geekosaur> one of the reasons is that, before the state transition table is a state definition table that helps tie the source to the state table for inspection. last time I looked at happy diagnostic output it lacked that table, making it harder to map a state transition back to the source
22:13 <sphinxo> http://lpaste.net/1023912210432262144 is my .y ( the relevant parts )
22:13 <freeside> trifecta does a good job with that sort of thing
22:13 <sphinxo> it's somewhere in
22:13 <geekosaur> (and they're cross-referenced with respect to shift/reduce and reduce/reduce conflicts, making it even easier)
22:13 <sphinxo> func :: { Func }
22:14 <jle`> i was in a situation earlier when i really wanted linear types
22:14 <jle`> but we did not have them
22:14 <jle`> now i am sold on their utility
22:14 <jle`> it's funny how i didn't realize how much i needed them until i heard about them
22:15 <jle`> the thing about learning haskell is that it makes you greedy for more language features v.v
22:15 woffs_ joined
22:15 JagaJaga joined
22:16 <sphinxo> can anyone spot what is wrong in my grammer? for state 97
22:17 woffs joined
22:18 Micamo joined
22:19 <geekosaur> sphinxo, I *think* the real problem is that it can't tell when something is an empty list(param) followed by nonempty list(sexp)
22:19 <geekosaur> or something related to that
22:19 <geekosaur> basically there's too much "optional" going on, between name being optional and lists being possibly empty
22:20 <sphinxo> why might it fail on both nonempty?
22:20 <geekosaur> that's the case it wouyld handle
22:20 woffs left
22:20 <geekosaur> the case it will mishandle is empty param list + sexp list that has cases that can be confused with param list
22:21 <Zemyla> edwardk: I figured out how to do liftReadsPrecRep.
22:21 <geekosaur> in actual lisp, the param list is mandatory (but can be nil/()) for this reason
22:21 dan_f joined
22:21 <MarcelineVQ> jle`: what was your use case?
22:21 synthetica joined
22:21 <infinity0> is there a typeclass that defines a "swappable" monad somewhere
22:22 <jle`> infinity0: what is a swappable monad
22:22 ikke joined
22:22 <merijn> infinity0: What do you mean by swappable?
22:22 <synthetica> Do you mean "Traversable"?
22:22 <Zemyla> liftReadsPrecRep :: (Traversable f, Distributive f) => (Int -> ReadS a) -> String -> Int -> ReadS (f a); liftReadsPrecRep ra nm = readsData $ readsUnaryWith (\p -> St.runStateT $ traverse getConst $ distribute $ Const $ St.StateT $ ra p) nm id
22:22 <infinity0> class Monad m => SwappableMonad m where swap :: Monad n => m (n a) -> n (m a)
22:22 <synthetica> infinity0: Thtat's basically Traversable.
22:22 <synthetica> *That's
22:22 <infinity0> ah, ok thanks
22:22 <jle`> that's Traversable, and it only requires a Functor constraint
22:22 <jle`> not everything has to be a monad :o
22:23 <jle`> ( useful types ... .... ( monads ) )
22:23 <synthetica> :o
22:23 <jle`> (my venn diagram)
22:23 <infinity0> i was just reading up on composing monads and this "swap" function came up so was wondering if there was already a typeclass for it
22:23 <jle`> oh, in that case, Traversable won't do
22:23 <jle`> Traversable's swapping (sequence) doesn't preserve Monad laws
22:23 <infinity0> ah ok
22:24 <jle`> the one that does is called Distributive
22:24 <jle`> but distributive functors are much more rare than traversable functors
22:25 <infinity0> i see
22:25 <infinity0> it says "dual of traversable", interesting
22:25 <synthetica> So, I have this datatype representing a sort of binary search tree, defined as follows: `data Sequ elem = Nil | OCons (Sequ (Pair elem)) | ICons elem (Sequ (Pair elem))`. I'm trying to implement Foldable for it, but is there a better way than just extracting the first element over and over?
22:25 <jle`> yeah. the difference here is that 'distribute''s laws are enough to prove that the composition of the two monads is itself a monad
22:25 tomphp joined
22:25 harwiltz joined
22:25 <jle`> but traversable's laws are much weaker
22:26 <Zemyla> If a Functor f is Distributive, then it's saying that f is equivalent to (->) e.
22:26 silver_ joined
22:26 <jle`> MarcelineVQ: in my case it was less resource management and more for guiding my program writing
22:27 <infinity0> oh man i need to pick up category theory again, last time i tried getting into it i stopped just before adjoints, still have no idea what those are
22:27 <infinity0> just about managed to realise preorder = directed graph, partial order = acyclic directed graph, sort of
22:27 augur joined
22:27 <harwiltz> Hello all. I'm trying to make a simple poker game in Haskell. So far I've defined a bunch of data, for example I've defined Cards and Decks, and a Table which is just a [Deck]. Would it make sense to make a Monad called PokerGame which takes a Table and a Deck parameter (the deck being the overall game deck, not just someone's hand), to somewhat automate the process of removing cards from the deck and
22:28 <harwiltz> updating the players' hands?
22:28 <jle`> synthetica: you can derive Foldable
22:28 <synthetica> Wait, seriously?
22:28 <jle`> yes, it's the "obvious" instance
22:28 <synthetica> (It's for a homework assignment, so I'm feeling like that would be... Cheating)
22:28 <jle`> it is likely that it would not be looked upon positively
22:28 <jle`> if that's the situation :)
22:29 <infinity0> harwiltz: sounds like the state monad would do what you need
22:29 <jle`> harwiltz: if you used State, the usefulness is that you can easily compose "card-removing" actions and sequence them one after the other
22:29 <jle`> and use it with mapM, sequence, etc.
22:29 <harwiltz> infinity0: Cool. Say I wanted to do this though, as an excercise to learn monads, would it be an appropriate approach?
22:29 <jle`> it would be good exerise to learn about State
22:30 <jle`> not sure about monads in general
22:30 <jle`> it wouldn't hurt though :)
22:30 <infinity0> first examples i find are useful to motivate the general concept later yeah
22:30 <infinity0> i can't understand abstract stuff without at least having 2-3 examples, then it's much much easier
22:30 <harwiltz> jle`: Ah, alright. Out of curiosity, since I'm having trouble understand the applications of monads, how often do you (or the average haskell programmer) create your own Monads?
22:31 <infinity0> harwiltz: for card games, a probability distribution is also a monad
22:31 hiratara joined
22:31 <merijn> harwiltz: You don't "create" monads, you simply realise some of your datatypes already are :)
22:31 <infinity0> ProbDist a = [(num, a)] with the nums adding up to one, you can define >>= on it for practise if you like
22:31 <synthetica> jle`: But I'll look into the algoritm for deriving it, probably could write it down myself then
22:31 <harwiltz> infinity0: So I should be defining some sort of shuffling activity within a monad?
22:31 <merijn> harwiltz: The same way you don't set out to "create a Functor", you write a datatype, then later realise it IS a Functor and then you implement fmap :)
22:32 <harwiltz> infinity0: Oh, cool. Thanks. I'm gonna do that
22:32 <jle`> harwiltz: it's not quite "within a monad", it's with the State type
22:32 <jle`> harwiltz: the Monad typeclass just lets you uese State in monad-polymorphic functions like mapM and friends
22:32 <harwiltz> merijn: Yeah, you're right. But I don't know much about functor's either ;)
22:32 <infinity0> harwiltz: it's useful if you're modelling "all possible games" e.g. to figure out a strategy, but if you're just coding a game engine then it's probably not so useful
22:32 <Zemyla> infinity0: The nums don't need to add up to 1, even.
22:32 <infinity0> since you'd only use one result of the shuffle rather than modelling a distribution over all possible shuffles
22:33 <jle`> harwiltz: i recommend not thinking about State as a platonic ideal of monads, and that doing stuff with state is doing stuff with monads
22:33 <harwiltz> infinity0: Yeah, I guess I don't really need that then
22:33 <jle`> harwiltz: State is a useful *type* for composing stateful actions
22:33 dfeuer joined
22:33 <jle`> for example, if you had a function `Deck -> (Card, Deck)` that drew a card from a deck and returned a modified deck
22:33 <infinity0> i think if you're starting off monads, practising with state is a fine way to start and there's no need to confuse the newbie with abstract talk about "it's not general enough"
22:33 <harwiltz> jle`: Ah, I see. How often do haskell programmers define monads though?
22:33 <jle`> and you wanted to do it twice
22:34 <jle`> you can use the State type to help you turn a `Deck -> (Card, Deck)` into a Deck -> (Card, Deck)` tha does the same thing twice
22:34 <harwiltz> jle`: Thats exactly what I'm trying to do
22:34 <jle`> the fact that it's a monad doesn't let you do that
22:34 <harwiltz> jle`: Oh, ok
22:34 <jle`> it's the power of the specific State type
22:34 <jle`> like, Int lets you add together integers
22:34 <jle`> that's feature of the Int type
22:35 <infinity0> if you structure your code using the state monad, you will figure out which parts of your card logic is "monadic" and which is specific to your card game
22:35 <harwiltz> jle`: But isn't State's power possible because its a monad?
22:35 <jle`> no
22:35 <harwiltz> Oh. Haha
22:35 <infinity0> it'll be easier to understand if you do the code yourself, rather than having others try to explain it to you
22:35 <jle`> well, you might have the causality backwards
22:35 <harwiltz> infinity0: Yeah, that's true
22:35 <harwiltz> jle`: It's a monad because it's powerful?
22:35 <jle`> the fact that it's a monad doesn't have much to do with how useful it is
22:36 <jle`> it's a useful type that is useful on its own. the fact that it's a monad is a coincidence
22:36 <harwiltz> jle`: Ok, but doesn't the monad part allow you to sequence actions?
22:37 <c_wraith> I mean.. Proxy is a monad, and Proxy is useful only for its phantom type.
22:37 <infinity0> the point is things don't have features "because it's a monad", it's the other way round
22:37 <jle`> it's not quite "it's a monad, so poof, you can sequence actions."
22:37 <merijn> Lemme jump in and recommend Wadler's original Monad paper
22:37 <jle`> harwiltz: but, State is something that you can sequence
22:37 <infinity0> the fact that it has a particular feature, is why it is called "a monad"
22:38 <harwiltz> Oh God. I'm so confused now, I'll stop and try to learn state before I completely make a fool of myself here ;)
22:38 augur joined
22:38 <infinity0> :)
22:38 <merijn> harwiltz: Wadler wrote a nice paper on a recurring patterns and showing what it is
22:38 <merijn> harwiltz: http://roman-dushkin.narod.ru/files/fp__philip_wadler_001.pdf
22:39 <harwiltz> merijn: Cool, thanks. I'm gonna read that
22:39 Jesin joined
22:40 <freeside> also, video avilable https://yow.eventer.com/yow-2013-1080/the-first-monad-tutorial-by-phillip-wadler-1359
22:40 <harwiltz> freeside: Oh nice, thanks!
22:40 <jle`> harwiltz: being a monad doesn't allow you to sequence it; it's a type that has a sequencing operation. that operation is a part of the type and its API
22:41 <harwiltz> jle`: Ok, I'm starting to see that now. I think what's at the root of all my confusion is that I've heard so much about how great Monads are, I can understand the characteristic monad functions and the rules, but I just don't understand the practical part
22:42 <harwiltz> Anyway, thanks jle`, infinity0 , merijn, freeside. I gotta go eat dinner now, seeya around
22:42 <freeside> eat a burrito.
22:42 silver_ joined
22:42 <jle`> i do recommend forgetting the hype :)
22:42 <merijn> harwiltz: Monad syndrome is generally overthinking this whole monad business :)
22:43 <jle`> day to day, when you use a type, you use it because of its specific usages. not because it's a monad or a monoid or whatever
22:43 <infinity0> harwiltz: the practical aspect is a common pattern you can use to better understand stuff you didn't realise was actually related before
22:43 oisdk joined
22:43 <merijn> harwiltz: When you look at it, there's honestly just not that much there. It's just that what's there is a very convenient reoccurring pattern
22:43 <infinity0> then you can use these common patterns to understand new stuff more easily
22:43 <jle`> like when i use Int, i don't use it because it has a Show instance, or because it has an Ord instance
22:43 <freeside> if you want to be a traditionalist, spend five years learning higher math, especially category theory, then write a tutorial of your own about how monads are trivially understood assuming you have five years of higher math
22:43 <jle`> i just use it because i need integers.
22:43 <infinity0> the pattern itself is not "super" impressive in the sense that they already exist elsewhere and you've already done them, just not in a way that makes it obvious you've done the same pattern 10 times
22:43 chaptastic joined
22:44 <jle`> when i use State, i don't use it because i need a Monad. i use it because i need to keep track and sequence stateful actions
22:44 mkoenig joined
22:45 <freeside> it's a bit like the realization, "oh my god, every person i have ever dated is deep down similar in some essential way that was not obvious to me but obvious to all my friends, but each of my friends explained it to me a different way"
22:45 <jle`> when i use lists, i don't use it because I need a Monad, or because i need a Monoid, or because i need an Ord or an Eq...i use it because lists are useful for keeping track of things in
22:45 Voldenet joined
22:45 Voldenet joined
22:46 louispan joined
22:47 <robertkennedy> When I write a function like `a -> (a,b)` I think I'm supposed to wrap it in a Monad. Which Monad?
22:47 <jle`> you...don't need to wrap it in anything...
22:47 <jle`> it's a perfectly fine function
22:47 <jle`> don't let anyone tell you you're supposed to wrap it in anything, heh
22:48 <mbw> robertkennedy: ^This, but also why should you be 'supposed' to do anything?
22:48 MindlessDrone joined
22:48 <freeside> enemy of the State
22:48 <Cale> robertkennedy: You *could* make that into State a b
22:48 <Cale> robertkennedy: But it's only of any value if you're chaining the a's together in a particular way
22:49 <jle`> sort of like, if you want to use Int with 'Writer', you can wrap it in a 'Sum' to give it a Monoid instance
22:49 <jle`> > foldMap Sum [1,2,3]
22:49 <lambdabot> Sum {getSum = 6}
22:49 <jle`> but to just use Int's normally, you don't need to wrap it in Sum
22:49 exferenceBot joined
22:50 <jle`> you only need to wrap it in Sum if you want to use it as a monoid and be able to mappend it
22:50 <robertkennedy> Sorry, yeah I am chaining them together - each function consumes some elements of a list
22:50 <freeside> http://krisnair.com/post/23954404803/think-like-a-mathematician
22:52 <jle`> robertkennedy: then yeah, wrapping an (s -> (a, s)) in 'State' gives you a pretty convenient way of sequencing them
22:52 d34df00d joined
22:53 <jle`> then you can do fun stuff like replicateM
22:53 <jle`> `recpliateM n (state f)` will "chain" your (s -> (a, s)) n times
22:53 louispan joined
22:55 <jle`> sequence [state f, state g, state h] will chain all of the (s -> (a, s))'s f, g, and h
22:55 tomphp joined
22:55 louispan joined
22:56 uglyfigu_ joined
23:00 <d34df00d> Hi!
23:00 chaptastic joined
23:01 <d34df00d> Is it possible to apply a polymorphic function in Uniplate's transformBi on every element that satisfies the function type requirements?
23:01 rkazak_ joined
23:01 <d34df00d> Along the lines of this:
23:01 <d34df00d> http://bpaste.net/show/5f81a8acd13f
23:01 AndreasK joined
23:04 <d34df00d> This approach fails with
23:04 <d34df00d> http://bpaste.net/show/eca8eacd5495
23:05 ramzifu joined
23:05 <Squarism> can you instruct haddock to link to hackage for libraries that are published there?
23:06 Rotaerk joined
23:07 path[l] joined
23:07 Jesin joined
23:07 chaptastic joined
23:08 xaviergmail joined
23:10 jdelreal joined
23:10 louispan joined
23:11 takle joined
23:11 <jdelreal> Got some colleagues wondering in Haskell how one would say/pronounce (what to call it): '>>>'
23:11 <jdelreal> ?
23:11 JeanCarloMachado joined
23:12 <jle`> it's commonly used as function composition
23:12 <johnw> compose
23:12 gienah joined
23:12 <jle`> 'composed with', maybe, but the order is a bit ambiguous
23:12 uglyfigurine joined
23:12 <jle`> f . g is called "f composed with g", but f . g is g >>> f, so
23:13 <freeside> you should stammer it out, like co-co-compose
23:13 <int-e> d34df00d: basically the answer is no. the fundamental difficulty is that there's no support for finding/constructing a type class instance given a TypeRep. From an abstract perspective, the fact that type classes are open plays a role here.
23:13 faberbrain joined
23:13 <jdelreal> One says: "andThen"
23:13 <jdelreal> ?
23:13 <jle`> but the reason why we have operators is because sometimes they're more meaningful than the corresponding words
23:13 <jle`> andThen is commonly used for >>
23:13 isenmann joined
23:13 <jle`> s/meaningful/expressive
23:13 <jdelreal> :-)
23:14 <jle`> in some situations, at least.
23:14 oisdk_ joined
23:14 vektorweg1 joined
23:14 <jle`> i've heard people say 'piped into'
23:14 <freeside> if > is "greater than", then >>> should be "greatest than". like, the greatest. absolutely the greatest operator. ask anybody. they'll tell you. just the greatest. we're gonna make operators great again.
23:14 <jle`> >>> is somewhat related to unix pipes
23:14 <Cale> Well, if it's reasonable to pronounce f . g as "f following g" then perhaps f >>> g might be pronounced "f preceding g" :)
23:15 <n1> instead of "composed with" one can say "after" or "following"
23:15 <n1> as Cale so rightly points out one second before me :)
23:18 dschoepe joined
23:18 wtetzner joined
23:19 <d34df00d> int-e: what options do I have? I've heard using Data/Typeable for Uniplate is not the only option, would it help? Would something like geniplate (never used it) help? And, from the abstract perspective, let's say I enable DataKinds and define my class as `class Smth (a :: Indexer)`. Would that (abstractly) work?
23:19 <d34df00d> The reason I'm asking is that I'd like to enumerate the types supporting/subject to a given operation just once.
23:20 guampa joined
23:20 louispan joined
23:21 conal joined
23:25 <jle`> types are erased at runtime, so you'd have to find a way to carry around a runtime witness
23:25 <jle`> like using Typeable
23:25 louispan joined
23:26 c0smo joined
23:26 <d34df00d> Yeah, but my types are already Typeable (as is one of the ways of working with Uniplate).
23:27 redmq_ joined
23:27 <jle`> in terms of typeable, you could pattern match on specific types and gain the instances for those specific types
23:28 <jle`> but you can't really do it for "any instance of class X"
23:28 <jle`> but if you know that thre are only a fixed set of instances for your typeclass, you can enumerate over all of those types
23:29 fDev2179 joined
23:29 safe joined
23:29 ziocroc joined
23:29 <jle`> there's just no way of finding an instance "in general" at runtime
23:31 <jle`> if you enumerate over each possible type explicitly, though, then GHC will gladly give you the proper instance.
23:31 nomicflux joined
23:32 tromp joined
23:33 danharaj joined
23:35 <ReinH> "backwards-composed"
23:35 rkazak_ joined
23:36 <johnw> I like that GHC keeps coming up with ideas that make me excited for the next version; now I want to play with linear typing :)
23:37 marcopullo joined
23:37 Welkin joined
23:38 zero_byte joined
23:38 mizu_no_oto joined
23:38 Lord_of_Life joined
23:39 redmq joined
23:42 path[l] joined
23:44 <c_wraith> only a year away..
23:44 <c_wraith> Oh, hey.. what's the 8.2 release schedule look like?
23:45 YongJoon joined
23:45 <hpc> wait ghc is getting linear typing?
23:45 yellowj joined
23:46 <johnw> hpc: http://blog.tweag.io/posts/2017-03-13-linear-types.html
23:46 <hpc> feature request: rust FFI that understands its type system
23:46 <hpc> (which has elements of affine types)
23:46 fDev2179 left
23:47 zcourts joined
23:47 louispan joined
23:47 dfeuer joined
23:47 <hpc> also i have to agree with johnw here
23:48 <hpc> i didn't think i could be excited for anything less than full dependent types in a new ghc
23:48 <hpc> but this is pretty cool
23:48 <c_wraith> I'm still excited about compact regions.
23:49 cardboard64 joined
23:49 fnordmeister joined
23:50 raycoll joined
23:54 mzabani joined
23:54 mhealy joined
23:54 <mhealy> hello, all
23:56 noan_ joined
23:56 mhealy left
23:56 mhealy joined
23:57 <michalrus> Can I somehow explicitly reference *this* module? Let’s say I define `error = 5` in it, but it clashes with `Prelude.error`. How can I reference `This.error`? But not having to write `MyApp.Some.FQ.Module.Name.error`.
23:58 JuanDaugherty joined
23:58 mhealy joined
23:58 <geekosaur> there is no shorthand for the current module name
23:59 <YongJoon> you can hide a method of `Prelude` or not importing `Prelude` implictly.
23:59 <Koterpillar> michalrus: import qualified MyApp.Some.FQ.Module.Name as F?
23:59 eacameron joined
23:59 <geekosaur> but you can import Prelude hiding (error)
23:59 <michalrus> Aw, very nice solutions! Thank you, all. :)