<    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 24 25  
26 27 28 29 30 31
00:02 <dolio> centril: Oh, they made all signatures in line?
00:02 <dolio> That's like the most persistent annoyance in Scala, I think.
00:02 <Welkin> it's like the same crap they did with swift
00:02 <Welkin> to make it more mainstream and generic of a language
00:03 <centril> dolio: http://rustbyexample.com/fn.html
00:03 <Welkin> languages made to appeal to everyone never do
00:03 <Welkin> because it actually appeals to no one at all
00:04 <centril> well, at least the return type is to the right and not like C, C++, Java
00:04 sqrt2 joined
00:04 <Welkin> one reason I think elm (as a language) is a failure
00:04 <centril> where it is to the left
00:04 <centril> Welkin: is because purescript is better?
00:04 <Welkin> centril: you can just use haskell
00:04 because[m] left
00:04 peterbecich joined
00:04 <Welkin> no need for purescript
00:05 <centril> also, functions in rust are not autocurried (yet)
00:05 <Welkin> but yes, purescript is what elm should have been (mostly)
00:05 doomlord joined
00:06 <centril> I guess the main motivation to why functions are not autocurried is because autocurrying makes the memory-behaviour of functions unclear
00:06 <centril> and rust is a systems programming language, so...
00:06 Rizy joined
00:07 <centril> hopefully Rust gets ACTs (associated type constructors) soon, so you can have monads monads monads
00:09 oish joined
00:11 <ertes> in such a way that you can write 'traverse' in rust?
00:11 MP2E joined
00:12 <centril> ertes: I don't see why not
00:12 <ertes> because rust lacks higher-kinded polymorphism
00:12 <ertes> which makes monads pretty useless
00:12 <centril> ertes: it does currently, but it will be added, almost certainely
00:13 <Welkin> why bother though?
00:13 <ertes> that's also why i don't understand the hype some people seem to have with monads in C# or F#
00:13 <Welkin> why not just use a haskell DSL to generate C?
00:13 <ertes> you can have the monadic interface in most languages, but the real reason to use monads is so that you can abstract over them
00:13 <centril> ertes: obviously
00:13 <centril> ertes: see: http://smallcultfollowing.com/babysteps/blog/2016/11/02/associated-type-constructors-part-1-basic-concepts-and-introduction/
00:14 <centril> and: http://smallcultfollowing.com/babysteps/blog/2016/11/03/associated-type-constructors-part-2-family-traits/
00:14 <centril> and: http://smallcultfollowing.com/babysteps/blog/2016/11/04/associated-type-constructors-part-3-what-higher-kinded-types-might-look-like/
00:14 <centril> and: http://smallcultfollowing.com/babysteps/blog/2016/11/09/associated-type-constructors-part-4-unifying-atc-and-hkt/
00:15 ziyourenxiang joined
00:15 dfeuer joined
00:17 <centril> iirc, HKTs are the reason you can't do instance Monad ((Flip Either) a) where ...
00:18 oisdk joined
00:18 <centril> Welkin: do you think you will get as good performance with a haskell DSL => C as with C directly ?
00:18 carlosdagos joined
00:18 <centril> or are you basically encoding C in haskell ?
00:19 <ertes> that looks like a sepcial case of HKT
00:19 <Welkin> you output C code
00:19 <ertes> why not just implement HKT and be done with it?
00:19 <Welkin> there are several libraries for this in haskell already
00:19 <Welkin> mostly for embedded c
00:20 <Welkin> centril: you "compile" to c, so there is no haskell at runtime, obviously
00:20 <ertes> it seems to me like most languages go out of their way to keep HKT out of their language… that's stupid
00:21 <centril> ertes: because: http://cstheory.stackexchange.com/questions/32260/decidability-of-parametric-higher-order-type-unification
00:21 halogenandtoast joined
00:21 <centril> (iirc)
00:21 <c_wraith> that's only an issue if you have arbitrary type functions
00:22 <centril> ertes: the posts explain their reasoning better than I can
00:22 <c_wraith> if you use only generative higher-kinded type constructors, the way base haskell does, that doesn't apply.
00:22 <c_wraith> Type families do lead to undecidable systems, which is why they are never considered the canonical type of something
00:23 nakal joined
00:23 <centril> c_wraith: generative HK TC being ?
00:24 <c_wraith> centril: generativity is the property that if f a ~ g b then f ~ g and a ~ b
00:24 <centril> c_wraith: ah
00:24 a3Dman joined
00:24 <ertes> centril: also undecidable ≠ unsafe… you just make sure not to use the undecidable subset of the language
00:25 <centril> ertes: right
00:25 <ertes> (or just insert a loop counter into the type-checker the way GHC does)
00:25 <centril> ertes: depth recursion limit ?
00:25 ragepandemic joined
00:26 mgaare joined
00:27 Mon_Ouie joined
00:27 peterbec` joined
00:27 sleblanc joined
00:27 <ertes> centril: not sure, if that's enough
00:28 <centril> c_wraith: is that the property that f a ~ g b => f ~ g , or f a ~ g b <=> f ~ g ?
00:28 <centril> (forall a b.)
00:28 <ertes> anyway, the point is that i don't see any real harm in undecidable type systems… undecidable ≠ unsafe
00:28 <centril> ertes: i agree
00:28 halogenandtoast joined
00:28 <centril> ertes: rust uses depth recursion limit iirc
00:29 e14 joined
00:29 <ertes> it does? for what?
00:29 peterbec` joined
00:29 pacak joined
00:30 <centril> ertes: https://sdleffler.github.io/RustTypeSystemTuringComplete/ (+ proof that rust is turing complete @ type checking)
00:30 <centril> "In most cases where the typechecker hits the recursion limit, something’s wrong with your program and it won’t compile no matter what. Only if you’re really mucking with the type system – like, say, writing seriously large Smallfuck programs with it – then maybe you’ll hit the recursion limit.
00:31 Schoolmeister joined
00:31 <dolio> You're not going to add higher-order unification to your type system and then fix it with a loop counter.
00:31 <centril> ===> \exists recursion limit
00:31 <c_wraith> I mean, GHC uses a recursion limit for the same reason when you enable UndecidableInstances.
00:32 <centril> c_wraith: right
00:32 hiratara joined
00:32 <dolio> It's not just a problem of being able to write loops, it's a problem of all kinds of choice points being added to the type checking.
00:32 <c_wraith> But that's not why higher-kinded types work.
00:33 <dolio> So if you ever make use of the 'feature', it's likely going to be by annotating a lot more things.
00:33 <dolio> Which actually makes the overall experience worse than doing it like Haskell.
00:33 parsnip left
00:34 Rizy joined
00:34 <centril> dolio: right
00:34 begriffs joined
00:34 Swizec_ joined
00:34 <centril> dolio: an example: rust doesn't have type inference for function definitions - i.e: they can't be elided since the type checking is much more local in rust (iirc)
00:35 pacak joined
00:35 jgt1 joined
00:36 <centril> anyways... it's an open discussion... nothing has been decided on which way to go (HKTs or ACTs)
00:38 tromp joined
00:38 <Tuplanolla> Every time I think about language design, I end up feeling that a consistently bad solution is better than an inconsistent but practical compromise.
00:38 <Tuplanolla> Is this a common obsession?
00:39 <centril> Tuplanolla: consistently bad solution = golang ?
00:39 <Tuplanolla> Not that bad.
00:39 <centril> Tuplanolla: :P
00:40 <Tuplanolla> Rather why have a type system at all if it can't be perfect.
00:40 <centril> Tuplanolla: had to pause for a second to parse the statement: "does she/he mean that golang isnt that bad, or that the solution shouldn't be as bad as golang"
00:41 <centril> now im unsure which one was intended
00:41 oisdk joined
00:41 <Tuplanolla> I shall leave it that way since it's an unimportant tangent.
00:41 <ertes> i've found a nice way to trace in a similar way to Debug.Trace, but with the ability to print hole-style errors (i.e. with full scope)
00:42 <ertes> trace :: a -> b -> b
00:42 <ertes> trace h x = unsafePerformIO $ do (x <$ evaluate h) `catch` \(SomeException ex) -> x <$ print ex
00:42 <ertes> you use it like this: trace _ myExpr
00:42 pacak joined
00:43 <centril> Tuplanolla: i never have this feeling... I consistently think that some small inconsistencies is better at some points than to have a consistently bad solution
00:43 <ertes> then whenever myExpr is evaluated, it displays everything in scope and then continues
00:43 <ertes> (needs -fdefer-types-holes)
00:44 Rizy joined
00:44 vaibhavsagar joined
00:45 <ertes> of course the usefulness may be limited due to how verbose GHC's error messages are
00:45 <centril> ertes: you still have to compile with the enable trace flag right ?
00:45 <centril> (forgot its name)
00:46 <ertes> centril: you need -fdefer-typed-holes
00:46 <ertes> nothing else should be needed
00:46 <centril> ertes: interesting!
00:46 <dolio> _ compiles to an exception that will show all the information it would print if you call `print` on it?
00:46 gpbaran joined
00:46 <Tuplanolla> That's pretty funny, ertes.
00:47 benjic joined
00:47 peterbec` joined
00:48 markus1209 joined
00:48 <Tuplanolla> Is the scope listing limited to five or however many items it is?
00:49 markus1219 joined
00:49 pacak1 joined
00:50 <ertes> Tuplanolla: indeed
00:50 <ertes> "(Some bindings suppressed; use -fmax-relevant-binds=N or -fno-max-relevant-binds)"
00:50 bixit joined
00:51 <ertes> well, also it only shows the types
00:51 Rizy joined
00:51 <ertes> i don't see a way to show values as well without TH
00:51 <centril> ertes: this was useful, thanks
00:51 <ertes> centril: probably not that useful, but it can help to print hole errors and still continue
00:52 <centril> =)
00:52 <ertes> normally holes are fatal in pure code
00:52 <centril> well, interesting at least
00:54 <ertes> i should have called it 'unholy'
00:54 Schoolmeister left
00:54 veeberz joined
00:55 <centril> ertes: now you just need to combine it with a function called "union"
00:55 <centril> ertes: unholy . union
00:55 tswett_to_go joined
00:55 tswett_to_go joined
00:55 tswett_to_go joined
00:56 <Tuplanolla> Tracing a hole is generally known as spelunking, ertes.
00:57 theDon_ joined
00:57 Guest__ joined
00:57 marcopullo joined
00:58 veeberz joined
00:59 yellowj joined
01:00 <Tuplanolla> This function deserves to exist for the sake of this pun alone.
01:00 <ertes> printing a hole is generally known as burning
01:01 dawehner joined
01:02 systadmin joined
01:03 <ertes> CMYKP
01:03 gpbaran joined
01:03 <ertes> cyan, magenta, yellow, key, power
01:05 <ertes> (yes, i had to look up what the K stands for)
01:05 cloudhead joined
01:05 <MarcelineVQ> you need all those to beat castle adventure
01:05 <ertes> that's why i prefer doom… you only need RGB
01:06 <cloudhead> what do people use for fast xml parsing these days?
01:06 <ertes> cloudhead: i use xml-conduit
01:06 <veeberz> Hello everybody. Can anyone recommend a haskell web framework for someone who wants to use haskell on the web just for kicks?
01:07 <ertes> veeberz: if 10 people answer your question, you will get 10 different recommendations
01:08 <Tuplanolla> How big kicks are we talking about here, veeberz?
01:08 ahri joined
01:08 <ertes> veeberz: servant may be the most kick-giving one right now (it does some fancy type-level things)
01:09 <cloudhead> ertes: thanks, hadn't seen that one
01:09 <ertes> cloudhead: depending on the application i might also use tagsoup
01:10 <ertes> but i don't know how fast that one is… hasn't been a bottleneck for me so far
01:10 <centril> how do we quantify for-kickishness?
01:11 deech joined
01:11 <cloudhead> ertes: yeah I have a 30gb file to parse, actually mainly need it to be event based because I can't hold it in memory
01:11 <centril> that's a big xml file o.O
01:12 <cloudhead> yeah it's a data dump heh
01:12 epsilonhalbe joined
01:12 mson joined
01:12 <centril> cloudhead: does it have to be XML? some other format might be terser and more efficient?
01:13 <cloudhead> I have no choice in the matter centril :/
01:13 <centril> :(
01:13 sophiag joined
01:13 <cloudhead> unless I convert it with another tool to json or something
01:13 <cloudhead> but yeah, that probably won't help much
01:14 <cloudhead> hmm there's hexpat also
01:14 <michalrus> Hey, is there some code available to use in your tests that checks various laws of your custom Monads, Functors etc.?
01:14 jeltsch joined
01:14 <greymalkin> Is there any elegant way to deal with marshalling data from one Lazy ByteStrings to strict ones? I'm connecting Yesod and GraphViz -- Yesod likes strict, and GraphViz likes lazy, and I'm getting tired of writing "fromStrict" all over the place.
01:15 <centril> cloudhead: why not MessagePack ?
01:15 <centril> cloudhead: https://en.wikipedia.org/wiki/Comparison_of_data_serialization_formats
01:15 <ertes> cloudhead: xml-conduit has a streaming version (hence the name), but i haven't used it myself
01:15 <MarcelineVQ> michalrus: http://hackage.haskell.org/package/checkers is one
01:15 <cloudhead> centril: sure, but in any case I'll have to traverse the xml, so I may aswell just use it directly
01:15 <sophiag> hi. i'm trying to install pcre-light and getting an error message that pkg-config can't be found. i'm confused about what's going on here
01:15 <michalrus> MarcelineVQ: thank you! :)
01:15 <centril> cloudhead: right =)
01:16 <ertes> cloudhead: even streamed it may take long, so if you find a way to export the data in another format, do so
01:16 <ertes> i maintain that XML is neither machine- nor human-readable
01:16 <centril> ertes: yup
01:16 <centril> that about sums it up
01:17 <cloudhead> ertes: haha yes, indeed
01:18 <centril> for human readable TOML is nice
01:18 <ertes> cloudhead: if your data is inherently tabular, consider using CSV
01:18 <cloudhead> csv is great
01:18 <centril> BSON / MessagePack for machine dependending on if you need to send it over network or not
01:18 <cloudhead> wish it was in csv
01:18 <ertes> it's about the fastest to parse format i can think of that has ready-made parsers in haskell
01:19 <centril> ertes: one is seldom so fortunate to have CSVs:able data
01:19 carlosdagos joined
01:19 cschneid_ joined
01:20 <ertes> cloudhead: if the XML is sufficiently uniform, you can write a small pseudo-XML converter without actually parsing XML
01:20 <ertes> if not, i'd go with JSON
01:20 <ertes> (or BSON i guess)
01:20 <cloudhead> ertes: ah you mean to just write a custom parser
01:22 <ertes> cloudhead: it's not the best idea in the world, but if this is a one-off job and the XML is very uniform, it may reduce parsing time by a significant factor
01:23 <cloudhead> yeah it's a clever idea
01:23 <cloudhead> since the xml is machine generated, it could work
01:23 <ertes> yeah… "clever"… in the bad sense… usually i would scream at people for doing that =)
01:23 <cloudhead> but I'll try with an xml lib first since I don't want to go down that rabbit hole yet
01:23 <cloudhead> hehe
01:23 <cloudhead> s
01:23 <cloudhead> ye
01:27 systadmin joined
01:27 mbw joined
01:28 <lpaste_> df pasted “f” at http://lpaste.net/8260766833850712064
01:28 <lpaste_> df pasted “f” at http://lpaste.net/4458148067241099264
01:28 <lpaste_> df pasted “f” at http://lpaste.net/353697
01:28 gpbaran joined
01:29 raycoll joined
01:29 mexisme joined
01:29 dawehner joined
01:30 AustinTasseltine joined
01:30 benjic joined
01:33 <orion> Is (IO a) defined as a data type or a function?
01:33 tswett_to_go joined
01:34 <kadoban> IO a is a type. Value of that type are not functions
01:35 bjz joined
01:35 <Maxdamantus> Depending on the context, `IO` might be considered to be a function instead of a type.
01:35 <Maxdamantus> but `IO a` would be a type.
01:35 <glguy> IO is also a type
01:36 <orion> "That said, if you look at GHC's source code, you'll find that it represents IO a as a function looking like State# RealWorld -> (# State# RealWorld, a #)" http://stackoverflow.com/questions/9244538/what-are-the-definitions-for-and-return-for-the-io-monad
01:36 <Maxdamantus> Yeah, under some fuzzy use of the term "type" (which iirc the Haskell report does use)
01:36 <glguy> certainly not fuzzy, also yes it's the terminology haskell uses
01:37 <glguy> orion is asking about implementation details of IO
01:37 <Maxdamantus> Well, technically I think it makes sense to refer to things of kind * as "types".
01:37 <Maxdamantus> ie, things that values have the type of.
01:37 <glguy> sure, those are types too
01:37 <mbw> Hello everyone. Is there actually any *introductory* material about web-client programming with Haskell to be found anywhere? And I really do mean introductory, since: 1. I have no experience in languages like PHP, JS (I am stupid and need types!) or other languages used for these kind of tasks, 2. I have NO formal background in Computer Science. Most tutorials I have found seem to assume some experience. I
01:37 <Maxdamantus> There is no value or even expression that has the type "IO"
01:37 <mbw> only want to be able (for example) to pull a website and extract all links to images, at least on that level for starters, while STILL being able to reason about what all that GET/POST stuff, XML/JSON, yada yada is all about. For now I am afraid I'll have to settle with something like "Web-Client Programming with Perl" and translate the examples...
01:37 <Maxdamantus> :t let x :: IO in x
01:37 <lambdabot> error:
01:37 <lambdabot> The type signature for ‘x’ lacks an accompanying binding
01:37 <glguy> right, it's types with kind * that have values
01:37 <Maxdamantus> eh, let's try that again.
01:38 <Maxdamantus> > let x :: IO in x
01:38 <lambdabot> error:
01:38 <lambdabot> The type signature for ‘x’ lacks an accompanying binding
01:38 <Maxdamantus> Damn. They changed the error.
01:38 <Maxdamantus> That used to say "expected a type, but `IO` has kind * -> *"
01:38 gpbaran joined
01:39 <geekosaur> not sure that isn't the same issue as earlier; something's gone odd
01:39 systadmin joined
01:39 <geekosaur> like, maybe that error is actually because we lost ScopedTypeVariables extension and therefore pattern bindings
01:39 <glguy> the distinction is about levels, values, types, kind s
01:40 <glguy> we don't claim that function values are not values
01:40 <Maxdamantus> Oh, oops, I'm silly.
01:40 <Maxdamantus> > let x = x :: IO in x
01:40 <lambdabot> error:
01:40 <lambdabot> • Expecting one more argument to ‘IO’
01:40 <lambdabot> Expected a type, but ‘IO’ has kind ‘* -> *’
01:40 <Maxdamantus> The error is the same. GHC calls * a type.
01:41 <Maxdamantus> rather, it calls the type-level things that have kind * "types".
01:41 <glguy> well have to create a ticket to fix it
01:41 <Maxdamantus> tbh I'd rather fix the terminology in the Haskell report :(
01:42 <glguy> thanks for being honest
01:42 sanett joined
01:42 revprez joined
01:42 <geekosaur> keep in mind the Report was not written with type level hackery in mind
01:43 <geekosaur> although that argument leads to "in a more advanced world, more precision in terminology is needed"
01:43 <Maxdamantus> Well, if you read any papers about kind theory, I suspect they would try to avoid calling things with kind `* -> *` "types".
01:43 <Maxdamantus> and would instead try to reserve that word for things of kind `*`
01:44 <glguy> i wouldn't suspect that
01:44 <geekosaur> maybe early ones, for the same reason: nobody had had reason to work out the terminology yet
01:45 <Maxdamantus> * -> * is just a function
01:45 <glguy> again this is like arguing that functions aren't values, it doesn't make sense in a world like Haskell where there are so many interesting first class things
01:45 <Maxdamantus> Particularly, one that works at a type level (if there is such a distinction)
01:46 <geekosaur> "type function", yes
01:46 <geekosaur> ghc even uses that terminology in a few places
01:46 <glguy> no, * -> * is a kind, it's not a function, you can't apply it to anything
01:46 <geekosaur> ...and it's not surprising that parts of ghc still use 1998 type theory terminology
01:46 <Maxdamantus> glguy: I meant things of kind * -> *
01:46 dmwit_ joined
01:46 <Maxdamantus> `* -> *` itself is a kind, yes.
01:47 <Maxdamantus> in the same way that `putStrLn "foo"` is not `IO ()`
01:47 <centril> glguy: sure you can... just not at the value level...
01:47 <centril> or well... something with kind * -> * can be applied
01:47 <glguy> centril, right
01:47 doomlord joined
01:48 <glguy> next you'll tell me that with DataKinds enabled that 'Nothing isn't a type ,
01:48 <glguy> but it's a type with kind 'Maybe a
01:48 epsilonhalbe left
01:48 <ubsan_> not... really?
01:49 <glguy> yup, really
01:49 <glguy> err kind Maybe a, no '
01:49 <Maxdamantus> Idris> :t IO
01:49 <Maxdamantus> IO : Type -> Type
01:49 <Maxdamantus> and yes, if you had a type constructor that took a `Maybe a`, it would have `Maybe a` somewhere instead of `Type`
01:50 <ubsan_> glguy: Nothing doesn't follow the definition of Type
01:50 <glguy> don't forget that "type constructor" has nothing to do with kind
01:50 <ubsan_> it's not a category of things
01:50 <glguy> it's a category of names
01:50 <ubsan_> it's a value of the type Maybe a
01:51 <ubsan_> DataKinds just allows you to write type constructors which depend on values
01:51 <glguy> ubsan_: no, this is about data kinds
01:51 <geekosaur> wake me up if y'all ever settle on a common language :p
01:51 <ubsan_> it doesn't make the values into types
01:51 <glguy> no, it lifts the data type definition into the type level
01:51 <glguy> not the values themselves
01:52 <Maxdamantus> glguy: er .. if you're in favour of the Haskell report terminology it kind of does.
01:52 <Maxdamantus> From the report: > The symbol * represents the kind of all nullary type constructors.
01:52 Destol joined
01:52 <ertes> jophish: about vulkan: is it usable though? if yes, i would contribute a small patch to fix the version bounds, if you don't have time to do it yourself
01:52 <nshepperd> well this is horribly confusing
01:52 <glguy> no the haskell report is quite clear that type constructor is a name category
01:52 mexisme2 joined
01:52 <glguy> constructors and variables
01:53 <ertes> jophish: i'd like to experiment with the vulkan API
01:53 <Maxdamantus> glguy: "a name category"? You mean it refers to `Boolean` but not `Maybe Int`?
01:53 <ubsan_> glguy: what are the terms of type Nothing
01:53 <glguy> Maxdamantus: Yes, Int, and Maybe are type constructors
01:53 <Maxdamantus> glguy: what about `Maybe int`?
01:53 <Maxdamantus> er, `Maybe Int`*
01:53 <glguy> Maxdamantus: That's a type with kind *
01:53 <ubsan_> `*` == `type`
01:54 <ertes> jophish: i'm particularly interested in the compute part right now, although i'd also like to try vulkan graphics at some point
01:54 <Maxdamantus> glguy: but * is the kind of nullary type constructors.
01:54 <glguy> Yes and other things too
01:54 <ubsan_> it's just that haskell has weird syntax
01:54 <Maxdamantus> glguy: (according to the statement I quoted from the report)
01:54 yearir joined
01:54 <glguy> There are six kinds of names in Haskell: those for variables and constructors denote values; those for type
01:54 <glguy> variables, type constructors, and type classes refer to entities related to the type system; and module names
01:54 <glguy> refer to modules
01:54 <centril> ubsan_: i find * -> * more terse than Type -> Type
01:54 sanett joined
01:55 <ubsan_> centril: terse != better
01:55 <centril> in this case it is imo
01:55 <ubsan_> I also find non-purity more terse than purity ;0
01:55 <ubsan_> *;)
01:55 <ertes> centril: you know, i'm glad that Maybe is called Maybe and not "?"
01:55 <centril> ertes: haha :D
01:55 <ertes> although i wouldn't mind Either being called "+"
01:55 <ubsan_> centril: I'd like to point out, type theoretists like me *hate* that notation
01:56 begriffs joined
01:56 <ubsan_> haskell infects people
01:56 <ubsan_> and gives them terrible syntax
01:56 <ubsan_> like `::`
01:56 <ubsan_> and `*`
01:56 <ertes> ubsan_: terse lists are more important than terse type annotations, i guess
01:56 <centril> ertes: nah, they're not
01:57 <ertes> and of course you should use recursive functions for lists everywhere
01:57 <centril> how often do you write type annotations and how often do you cons lists?
01:57 <ertes> foldr is evil
01:57 <nshepperd> f (a::b::c::xs) = ... -- nah...
01:57 <ertes> centril: i'm being sarcastic
01:57 <centril> ertes: oh
01:57 <centril> ertes: sarcasm in text is hopeless
01:58 <ertes> nshepperd: f (a :: b :: c :: xs) = …
01:58 <ertes> not that bad
01:58 <centril> ubsan_: im keeping * -> * tho, even tho it bugs you ^^
01:58 <ubsan_> centril: well, not like we can change haskell now
01:58 <centril> ubsan_: except that Type :: *
01:58 <ubsan_> centril: I'd love to replace it with idris though ;)
01:59 <ubsan_> centril: hmm?
01:59 <centril> ubsan_: GHC 8 added TypeInType
01:59 <ertes> when the kind system was designed, there used to be only one kind for concrete types… why they chose to call it "*" instead of "T"? beats me
01:59 <nshepperd> you can say Type in haskell now
01:59 <ertes> "*" is the worst choice
01:59 <centril> ertes: it looks pretty
01:59 <ertes> it looks horrible
02:00 <centril> giving a fuzzy feeling
02:00 <centril> ertes: who doesnt like starts?
02:00 <nshepperd> it's inconvenient because with typelits we want to use * for multiplication too...
02:00 conal joined
02:00 <tswett_to_go> I dunno, the worst choice might have been a surrogate code point or something.
02:00 <ertes> i do like stars… for products
02:00 <ubsan_> centril: so * :: *?
02:00 <centril> ubsan_: yes
02:00 <Maxdamantus> Is a surrogate codepoint a normal codepoint that requires a surrogate pair when represented in UTF-16?
02:01 <ubsan_> centril: are there implicit universes?
02:01 <tswett_to_go> Maxdamantus: no, it's one of the two things that makes up a surrogate pair.
02:01 <Maxdamantus> tswett_to_go: oh, those are code units.
02:01 <ubsan_> I'm not sure exactly how to say that
02:01 <Maxdamantus> Sorry, more technical terminology.
02:01 <nshepperd> it's illegal in utf-8
02:01 <centril> ubsan_: https://ghc.haskell.org/trac/ghc/wiki/DependentHaskell/Phase1
02:01 <ubsan_> gah there's a word I'm looking for
02:02 <ubsan_> implicit universe ordering
02:02 <nshepperd> Maxdamantus: isn't a code unit the representation in bits?
02:02 <ertes> ubsan_: cumulative?
02:02 <tswett_to_go> Yeah, officially, a surrogate code point can't be represented in any encoding.
02:02 <Maxdamantus> Right, the values that are used as the code units in UTF-16 surrogate pairs are not valid codepoints.
02:02 <ertes> ubsan_: idris does that
02:02 <centril> ertes: i thought that's what idris has
02:02 <Maxdamantus> (just because unicode has reserved those numbers)
02:02 <ertes> yes
02:02 Cell joined
02:02 <ertes> haskell doesn't do it though
02:02 <nshepperd> so it's a fake codepoint basically
02:02 <ertes> "TypeInType" is meant literally
02:03 <ertes> so indeed: Type :: Type
02:03 <Maxdamantus> nshepperd: a code unit is the unit used in the encoding. eg, in UTF-8 the code units are the octets that make up the UTF-8 string.
02:03 <ubsan_> ertes: whether it's cumulative or not doesn't really matter, you just need some way to represent ordering so that `Type :: Type` is not literally true
02:03 <Maxdamantus> nshepperd: in UTF-16 they're the 16-bit integers that make up the UTF-16 string.
02:03 <ubsan_> although apparently, Haskell chooses not to do that
02:03 <centril> ubsan_: it's not consistent as a logic
02:03 <ertes> ubsan_: yeah, haskell doesn't
02:03 <ubsan_> centril: no it is not
02:04 <tswett_to_go> It's pretty obvious how surrogate code points *would* be encoded in UTF-8 and UTF-32. You just ignore the fact that you're supposed to check for them and reject them.
02:04 <ertes> it collapses all universes into one: Type
02:04 <ubsan_> ertes: that annoys me
02:04 pwnz0r joined
02:04 <centril> ubsan_: well, what's one more way of proving bottom when you already can do it ?
02:04 <ubsan_> centril: ... yeah, I guess :/
02:05 <centril> ubsan_: how mature is Idris?
02:05 <ubsan_> centril: fairly
02:05 <ertes> ubsan_: well, i don't see a way to add hierarchial universes to haskell easily… they need quite a bit of extra type-level machinery
02:05 <ubsan_> nowhere near haskell levels
02:05 <centril> ubsan_: i guess im sticking with haskell for now then
02:05 <ubsan_> it needs a lot more library support, and better compilation output
02:05 <ubsan_> ertes: yeah, you're right
02:06 <centril> I guess I could not be a douche and contribute with the libs part...
02:06 <ertes> although if it were easy enough, there would be no real reason not to add them
02:06 <centril> libs aren't going to magically appear so to speak
02:07 <ertes> now that haskell introduced -XStrict, idris could introduce -XNonStrict
02:07 <centril> ertes: hah :P
02:07 Ayey_ joined
02:07 <ertes> right now, forcing me to use Lazy everywhere, idris is not that appealing to me
02:07 <ubsan_> lol
02:07 <glguy> If you might be interested in Idris, it'd be worth joining #idris
02:07 <centril> ertes: I want a -XCompromise flag too
02:07 <ubsan_> that's one of my favorite features of idris
02:08 <ubsan_> I dislike by-default lazy
02:08 <ubsan_> centril: I should probably do more idris, but now I'm working on my own hella-awesome language :D
02:09 <centril> ubsan_: how does dependent types + laziness factor into idris?
02:09 <ubsan_> centril: how do you mean?
02:09 <glguy> Idris is offtopic in #haskell, however
02:09 <centril> glguy: this is not strictly #idris, but rather #haskell compared to #idris
02:10 <tswett_to_go> Oh yeah, I've got a hella-awesome language.
02:10 <tswett_to_go> Unimplemented, of course. I don't, y'know, *do* stuff.
02:10 <ubsan_> tswett_to_go: mine is playing with dependent types + affine types in a systems language
02:10 pandeiro joined
02:10 <centril> ubsan_: like: apparently dependent types in haskell have been problematic to get right due to laziness (i dont know the details)
02:10 <centril> ubsan_: do tell... git repository ?
02:10 <tswett_to_go> My language is a database query language inspired by category theory.
02:11 <ubsan_> tswett_to_go: plus a helping of lvalue types, because that's one of my favorite things about C++
02:11 <tswett_to_go> Tables are objects. Foreign key columns are arrows.
02:11 <ubsan_> centril: the parser isn't even fully done yet lol
02:11 <ubsan_> mostly at this point it's design documents
02:11 <centril> oh
02:11 <ubsan_> sorry :3
02:11 <ubsan_> there's also a ton of crap on whiteboards
02:12 <ubsan_> <3 whiteboards
02:12 <centril> ill await it eagerly then
02:12 <tswett_to_go> I started implementing it in C#. Now that I've left it alone for a while, I'm thinking about whether Haskell might be a better option.
02:12 <ertes> ubsan_: i gave up trying to create such a language a long time ago, and recently i gave up on finding an alternative to haskell… today i just use haskell for that sort of thing
02:12 <centril> ubsan_: yes, <3 whiteboards
02:12 <ubsan_> ertes: see, I'm coming from the other direction :)
02:12 <ubsan_> I want to bring dependent types to a Rust/C++-alike
02:12 <ubsan_> b/c I'm weird
02:13 <ertes> i briefly tried various schemes, but i can't program without a type system
02:13 <centril> ubsan_: i want that too
02:13 <centril> ubsan_: const-dependent types in rust is a nice start
02:13 <ubsan_> tswett_to_go: I really love rust as a compiler language
02:13 <ertes> makes me shout at the compiler: "why are you so stupid?! it's obvious that i want you to do *this*, and if you had a type system, you would know that, too!"
02:13 <centril> maybe we can get full dependent types in rust
02:13 lifter joined
02:13 <ubsan_> centril: I look at rust, and I don't think it'll ever really have full dependent types
02:14 <ubsan_> there are too many backwards compatibility things
02:14 <ubsan_> that we'd have to completely change if we were to get dependent types
02:14 <ertes> i had a look at rust, too, and immediately came back to haskell
02:14 <ertes> "still no HKT polymorphism"
02:15 <centril> i dont know the compiler details, so i guess you're right ubsan_
02:15 <tswett_to_go> ubsan_: hmm, that's an interesting idea. Compiling a database query language wouldn't necessarily make much sense. But Rust has the whole...
02:15 <tswett_to_go> I was going to say Rust has the whole "no runtime system" thing going for it, but does it really?
02:15 <ubsan_> tswett_to_go: uh, yes
02:15 <tswett_to_go> I don't remember if Rust gives you a garbage collector or what.
02:15 <ertes> also rust as a compiler language? no way! i want HKT there, too, because i want easy locally nameless binding
02:15 <ubsan_> Rust is at C++ speed
02:15 <ertes> a la the 'bound' library
02:15 <tswett_to_go> *nod*
02:16 <ubsan_> ertes: *shrug*
02:16 <lifter> So I've done my Haskell development in vim, Sublime, and most recently Atom. But Atom is (surprise) giving me performance issues and I'm looking to move to something else. These days Haskellers are raving about Intero, right? If I want to try Intero but stick to my familiar vim bindings, what's the best emacs for me?
02:16 <mbw> lifter: I would guess spacemacs.
02:16 <* ubsan_> continues to use vim
02:16 <tswett_to_go> Say... I've been thinking about what parts of Haskell can just translate directly into C, without any garbage collector calls or anything like that.
02:16 <* centril> knows one vim command: :q!
02:16 <ertes> lifter: do you use stack?
02:17 <lifter> Yep!
02:17 infinity0_ joined
02:17 infinity0_ joined
02:17 <ertes> lifter: because it's hard-wired into intero
02:17 <ubsan_> tswett_to_go: I feel that probably, affine types would help a lot here
02:17 <ubsan_> or no wait, they're linear types, aren't they
02:17 <ubsan_> well, linear arrows, at least
02:17 <lifter> OH! One more thing I forgot, I'd really like to have the ability to make multiple cursors if at all possible, like you can do w/ Sublime and Atom. Anyone know if you can do that in spacemacs?
02:17 <mbw> lifter: Also using Atom with only 4GB Ram and without a swap file is going to result in a bad time, so I get where you're coming from. What kind of issues do you have with vim + stack?
02:18 <ertes> lifter: yes, someone wrote an extension for that… it's literally called multiple-cursors
02:18 <ertes> lifter: you can get it from MELPA, like most other things
02:18 <lifter> mbw: Honestly, I can't even remember why I switched from vim, ic might have been for the multiple cursor thing.
02:18 <tswett_to_go> Most Haskell types aren't "just a struct", but it's easy to create ones that are.
02:18 <ubsan_> tswett_to_go: hmm?
02:19 <ubsan_> tswett_to_go: a lot of haskell types can be done with tagged unions
02:19 <ertes> lifter: there is also an extension by the same guy to have multiple regions (emacs terminology for marked stuff)
02:19 <ubsan_> a la Rust
02:19 <tswett_to_go> Like, most Haskell types don't encode directly as a sequence of bytes of a specific length. Take, say, Maybe Int.
02:19 <mbw> lifter: Wouldn't block insertion mode (ctrl+v; shift+i/a) be a valid poor man's substitute for that kinda thing?
02:19 <lifter> ertes: I did actually use emacs way back in the day, too...
02:19 <tswett_to_go> That could be pretty complicated: Just (error "you can put a really long string here and you still simply have a Maybe Int")
02:19 <ertes> lifter: so you search for a piece of text or a regex and edit all instances of it at the same time
02:19 infinity0 joined
02:19 <ubsan_> tswett_to_go: struct { enum Tag { Nothing, Just } tag; ptrdiff_t data; };
02:19 <ertes> (i went back to macros though)
02:20 <ubsan_> (using ptrdiff_t as `Int`)
02:20 carlosdagos joined
02:20 <lifter> ertes: Yeah.... you can go the all-regex route as well. Actually my regex foo has increased greatly since starting Haskell dev. :)
02:20 <ertes> lifter: BTW, just to provide some diversity: i use haskell-mode instead of intero with the very simple reason that i don't use stack =)
02:20 <tswett_to_go> ubsan_: so how do you encode Just (error "whatever") like that?
02:20 <ubsan_> tswett_to_go: that's... a thing?
02:20 <ubsan_> what?
02:21 lp joined
02:21 <ubsan_> what's up with haskell error handling, does every monad just have implicit state or something?
02:21 <ubsan_> > Just (error "hi")
02:21 <lifter> ubsan_: There are exceptions and exception handling mechanisms.
02:21 <lambdabot> Just *Exception: hi
02:21 <tswett_to_go> No... Haskell is just lazy.
02:21 <ubsan_> lifter: ugh, I forgot about that :/
02:21 <ertes> you can fix errors, too
02:21 <ertes> > fix error
02:21 <lambdabot> "*Exception: *Exception: *Exception: *Exception: *Exception: *Exception: *Ex...
02:22 <ertes> proving that you need laziness to fix errors
02:22 infinity0 joined
02:22 <mbw> Also you can use c++ and variant types (boost::variant or std::any, C++17) or any (same case as with variant), which kind of goes into that direction.
02:22 <tswett_to_go> Anyway, if you had a strict Maybe type--call it Smaybe--then Smaybe Int would be what I'm calling "just a struct".
02:23 <lifter> ubsan_: It's not too bad in my experience, the hard part is that actually there are a handful of ways to deal w/ errors and it's a little overwhelming at first.
02:23 <tswett_to_go> It's one byte or whatever to indicate whether it's Nothing or Just, plus whatever it takes to make an Int.
02:23 <ubsan_> tswett_to_go: the strict subset of haskell is easily convertible, at least
02:23 <ubsan_> and anything that works under strictness
02:23 <ertes> tswett_to_go: i don't think that's true
02:23 veeberz joined
02:24 <ubsan_> ertes: sure it is
02:24 <ubsan_> although it won't be a byte
02:24 <lifter> could be a single bit!
02:24 <ubsan_> it'll be max(byte, alignof(Int))
02:24 <ertes> even strict Maybe needs a few bytes
02:24 Rodya_ joined
02:24 <ubsan_> ertes: why?
02:24 <ertes> most likely a whole machine word
02:24 <ertes> ubsan_: because GHC
02:24 <tswett_to_go> If you put the Int first, does that let you do it in only 9 (for 64-bit Ints) bytes?
02:25 <ubsan_> tswett_to_go: yeah, but the alignment still pulls the size out to 16
02:25 Wizek joined
02:25 <lifter> Int size depends on architecture
02:25 <ubsan_> for arrays and such
02:25 meba joined
02:25 <ertes> unless it can optimise the constructor away, it will probably take something like 4-8 bytes depending on target
02:25 infinity0 joined
02:25 <mbw> Plain-old enum does not make any guarantees about the type used internally, only that it's convertible to/from int. That's why they added enum classes to c++11.
02:25 <tswett_to_go> Hmm, right.
02:25 Wizek_ joined
02:25 <centril> tswett_to_go ubsan_ ertes : damn guys, so much interesting happening in #haskell - so hard to study :P
02:26 <ubsan_> centril: muahahahaa
02:26 <tswett_to_go> I know, right?
02:26 <tswett_to_go> I'm supposed to put in 9 hours of work today.
02:26 <u-ou> !lurk
02:26 <tswett_to_go> It's 10:30pm and I haven't started yet.
02:26 <centril> tswett_to_go: hah :D
02:26 <tswett_to_go> I feel like tonight is going to have a Bitter End.
02:27 <centril> I'll just have to read the backlog later on and see what happened
02:27 <tswett_to_go> By which I mean that some time around 2am, I'll probably be going to the only 24-hour coffee shop in the city, the Bitter End.
02:27 <halogenandtoast> nshepperd: Thanks for you answer yesterday, I got caught up and didn't see it
02:27 <ertes> tswett_to_go: switch to your editor, open a haskell file, load it into GHCi
02:27 <centril> OK... im closing the to-IRC tmux attachment for now then
02:28 sleblanc joined
02:28 Rainb joined
02:28 infinity0 joined
02:28 <ubsan_> tswett_to_go: sounds fun
02:28 <tswett_to_go> Is it really the only one? I'd say Grand Rapids is a medium-sized city; we really should have more than just one 24-hour coffee shop.
02:28 <ertes> tswett_to_go: if you have trouble doing that, get a second screen… you can watch #haskell on it and still get stuff done
02:28 <tswett_to_go> "you can watch #haskell on it and still get stuff done" - nope, not possible under any circumstances. :)
02:28 <mbw> How about a tiling window manager? Been using i3 for about 2-3 years now and I am more than happy with it
02:29 <ertes> mbw: on an ultra-wide screen perhaps
02:29 <ogkloo> i3 is great
02:30 <barrucadu> I have #haskell open while working, and something catches my eye, and I stop working. It can't be done.
02:30 <ubsan_> y'all are keeping me from working on my parser
02:30 doomlord joined
02:30 <ertes> with the haskell buffer on the left side and the haskell-process buffer on the right, my screen space is pretty much used up =)
02:30 <ubsan_> I've written it two times already, and I'm going in for a third
02:30 <u-ou> im reading the channel while playing emulators
02:30 <mbw> I usually have like 4-5 desktops open, each in full-screen with one terminal window open. Switching between those is something you become used to quickly.
02:30 <ubsan_> u-ou: ooh, what do you play?
02:30 <ubsan_> I've gotten super into kaizo lately :D
02:30 <u-ou> sonic rn
02:30 <tswett_to_go> Decisions, decisions. Should I work, or should I stay on my personal laptop watching this Karpathy neural net training on a picture of Gumball Watterson?
02:30 infinity0 joined
02:30 <tswett_to_go> At work I have a 3-display setup, and I really miss it when I'm not working.
02:30 takle joined
02:31 <MarcelineVQ> good stuff, there's an #haskell-offtopic channel for this line of convo though :>
02:31 <u-ou> what about haskell-blah!
02:31 <u-ou> that's the REAL offtopic channel
02:31 <ubsan_> you know what are really cool?
02:31 <ubsan_> lenses
02:32 cyborg-one joined
02:32 <u-ou> my haskell is very rusty. haven't touched it in a while. going to read that book by bite-my-app
02:32 <ubsan_> u-ou: my haskell is also very rusty
02:32 <ubsan_> so is my C++
02:32 louispan joined
02:32 <ubsan_> and my idris :3
02:32 <u-ou> oh NO
02:32 <u-ou> :p
02:32 <tswett_to_go> Yeah, lenses are cool! I'm probably going to explicitly build them into my database language.
02:32 <u-ou> I can't believe I did that
02:33 <ertes> tswett_to_go: must be quite a powerful language
02:33 <mbw> I would've loved to try Agda, if it wasn't so opinionated about using emacs :(
02:33 <ubsan_> tswett_to_go: lenses are even cooler with linearity
02:33 <ertes> because you need one for lenses =)
02:33 infinity0 joined
02:33 <ubsan_> mbw: use a better language!
02:33 <ubsan_> like coq
02:33 <ertes> @src Lens
02:33 <lambdabot> Source not found. Your mind just hasn't been the same since the electro-shock, has it?
02:33 <ubsan_> or idris
02:33 <ubsan_> or lean
02:33 <ubsan_> what the heck? lol
02:33 <ertes> lambdabot: you got it, tsunderebot…
02:34 <mbw> I decided on learning coq... like next week or so...
02:34 <u-ou> i want to learn prolog
02:34 <tswett_to_go> ertes: yeah, it's powerful because it has lenses built into it. :J
02:34 <u-ou> and haskell :p
02:34 <ertes> @botcookie
02:34 <lambdabot> Unknown command, try @list
02:34 <ertes> @botsnack
02:34 <lambdabot> :)
02:34 <u-ou> heh
02:35 <u-ou> cute
02:35 <tswett_to_go> Unlike Haskell, which doesn't have lenses built into it, so obviously my language is strictly better than Haskell.
02:35 <ogkloo> where would I go to get ghci with ghc >v8
02:35 <ertes> lambdabot: picky, aren't you…
02:35 <ubsan_> tswett_to_go: linearity + lenses are cool, because you can optimize them down to lvalue writes
02:35 <ertes> ogkloo: what do you mean?
02:35 <mbw> ogkloo: Simplest would probably to install stack, then stack update && stack upgrade etc.
02:35 <ertes> ogkloo: GHCi comes with GHC
02:36 <mbw> Should result in a newer version than what comes with dist repos.
02:36 <tswett_to_go> Optimize down to lvalue writes. Note that my language is going to compile to Oracle SQL.
02:36 meff` joined
02:36 <ubsan_> tswett_to_go: D:
02:36 <ogkloo> ertes: so I've got stack 1.4, which I figured would have ghc v8, but running stack ghci gets me 7.10.3
02:37 <ogkloo> oh no wait I'm dumb
02:37 <ertes> tswett_to_go: exception handling is built into PHP, whereas in haskell it's a set of library functions… so PHP is superior?
02:37 <tswett_to_go> ...and other versions of SQL. Oracle SQL is merely the most urgent target, because it sucks. :)
02:37 baroncharlus joined
02:37 <tswett_to_go> ertes: yes, exactly!
02:37 <ertes> i see
02:37 <mbw> ogkloo: Did you change the resolver of the global project to a newer version?
02:37 systadmin joined
02:38 <tswett_to_go> And I use Oracle SQL all the time at work, so I'm acutely aware of the exact ways in which it sucks.
02:38 <ogkloo> mbw: I think I need to go do some primer on stack, I am woefully behind on that
02:38 baroncharlus left
02:38 <ertes> i'm suppressing most of my PHP memories, but i distinctly remember implementing iteratees many years ago, when they were popular in haskell
02:38 <mbw> ogkloo: Should be inside .stack/global-project/stack.yaml
02:39 <tswett_to_go> No booleans, no empty strings, extremely verbose table lookup syntax. One gigantic syntactic construct used for almost everything, instead of having a separate construct for each feature.
02:39 <mbw> Wait, iteratees aren't popular anymore? I always thought I should learn those some day. Don't pipes and conduit abstract over those?
02:40 <ertes> mbw: no
02:40 <mbw> That clears it up then, I guess.
02:40 <ertes> mbw: they are a different streaming abstraction… iteratees were abandoned, though i'm not exactly sure why
02:40 <ertes> however, pipes is definitely easier
02:41 <tswett_to_go> No first-class tuples, no obvious way to check nullable values for equality, easy to write nondeterministic code by accident.
02:41 <tswett_to_go> I'm going to stop now.
02:42 <mbw> Is there a valid reason to stick with Text/Bytestring.Lazy? I saw that wreq makes use of those internally, for instance.
02:42 marcopullo joined
02:43 <ertes> mbw: i still think learning them could expand your mind… they were a very interesting way to handle streaming, which was in a number of ways *simpler* than the more modern transducer-based approach (conduit/machines/pipes)
02:43 Ayey_ joined
02:43 <ertes> but they may be a bit difficult to understand at first
02:44 <ubsan_> has anybody checked out backpack?
02:44 <ertes> fun fact: the snap framework still uses iteratees =)
02:44 <ubsan_> (sorry, I sometimes switch from thought to thought quickly)
02:45 <ertes> oh, wait, i'm wrong… they switched to io-streams
02:45 mizu_no_oto joined
02:45 <mbw> I'm afraid of what will happen if I keep expanding my mind...
02:45 <ubsan_> ertes: sounds delightfully C++-y :P
02:45 <ertes> they did that with 1.0 apparently
02:46 brynedwardz joined
02:47 <systadmin> How come there's no while and for loops .-.
02:47 begriffs_ joined
02:47 <ertes> systadmin: haskell doesn't have statements the way most other languages have… instead it has first-class actions, and constructing looping actions is a matter of writing a function
02:47 raycoll joined
02:48 <ertes> systadmin: for example (c >> d) is the action that first runs the action 'a', then the action 'b'
02:48 <ertes> so you can read (>>) as "and then"
02:48 baroncharlus joined
02:48 <ubsan_> ertes: I would really hope that `c >> d` doesn't run `a` then `b`
02:48 <ertes> systadmin: forever action = action >> forever action -- (forever action) is the action that first runs 'action' and then the action (forever action)
02:48 <tswett_to_go> I've been writing purely functional code in Scala, and I've been doing it mostly in an imperative style.
02:48 <tswett_to_go> Haskell is taking a little getting used to.
02:48 tristanp joined
02:48 <systadmin> So I gotta learn to use recursions?!
02:48 <ertes> systadmin: does that make sense?
02:49 <systadmin> ertes: yep
02:49 <systadmin> so `forever` makes things run *forever*?
02:49 <ertes> systadmin: yes, understanding recursion is very helpful, even though you probably won't use it *directly* in most cases
02:49 pwnz0r joined
02:49 <ertes> systadmin: forever doesn't really "make"… it "is"
02:49 <mbw> systadmin: If you consider that Haskell makes a distinction between "functions" and something that can result in side effects in addition to returning a result, it makes sense that we don't use for loops. Since the canonical for loop is just a mapping from an iteration space to a sequence of side effects...
02:50 <orion> Is it accurate to call "(a, b)" a product of a and b, and "Either a b" a co-product of a and b?
02:50 <ubsan_> for : (initial : a) -> (cond : a -> Bool) -> (loop : a -> a)
02:50 <ertes> orion: the types? yes
02:50 <tswett_to_go> You don't necessarily have to actually write recursive functions... but it might be the easiest way to go sometimes.
02:50 <mbw> orion: (,) is also sometimes called an anonymous product.
02:50 <ertes> orion: in fact it's super-accurate, because you said "a product" instead of "the product" =)
02:50 <mbw> or rather (a,b).
02:51 <ubsan_> for initial cond loop = case (cond initial) of True => for (loop initial) cond loop | False => initial
02:51 <ubsan_> type of for should be `a -> (a -> Bool) -> (a -> a) -> a`
02:51 <sophiag> ok, circling back to ask this again... can anyone shed some light on my attmpes to install prce-light with cabal are failing due to not being able ot find pkg-config? this came up because it's a dependency for ghc-core
02:51 <ertes> systadmin: note that you could bring back most of your control constructs from other languages as regular functions… we do that for some things like exception handling
02:51 <tswett_to_go> ertes: of course, there's homotopy type theory, where you only have one of anything, and so it really is "the product"!... kind of.
02:51 <ertes> systadmin: for example 'catch' is a regular function in haskell
02:51 <ertes> :t catch
02:52 <lambdabot> Exception e => IO a -> (e -> IO a) -> IO a
02:52 systemfault joined
02:52 <ertes> systadmin: (IO a) is the type of actions that result in a value of type 'a'
02:52 doomlord joined
02:52 <ertes> it takes such an action and an exception-handler function
02:52 <ertes> (catch c f) is the action 'c' with exceptions caught by 'f'
02:53 AustinTasseltine joined
02:54 dan_f joined
02:54 <ertes> systadmin: however, you probably wouldn't want to bring 'for' loops back, because the way 'for' works depends a lot on the language's ability to have statements and state effects within those, which haskell doesn't have
02:55 tristanp joined
02:55 <ertes> instead you have things like folds and unfolds, while have a similar purpose in haskell as for-loops have in other languages, but are far more domain-specific (and therefore often shorter and less error-prone)
02:55 <ertes> s/while/which/
02:56 cmdd joined
02:56 robertkennedy joined
02:56 louispan joined
02:56 <ertes> example: mapM_ print [1..10] -- print numbers from 1 to 10
02:57 <mbw> systadmin: Also, people try to avoid "naked recursion", which would be something like using goto. Instead you use "common patterns of recursion" which get used over and over. Maps/Folds/etc. are recursion combinators which abstract out these patterns and makes code easier to reason with. It's analogous to using for_each constructs instead of a naked for-loop, since in the latter, indices might be changed in
02:57 <mbw> the loop body..
02:57 <mbw> (bringing goto into the game is probably a little harsh though...)
02:58 <Cale> You're certainly free to bring C-style for loops back yourself if you'd find them useful though -- it's easy enough to write one (but I wouldn't recommend it)
02:59 anuxivm left
03:00 hucksy joined
03:00 <c_wraith> It's actually kind of a pain to write something so general as to emulate every way a for loop can be abused.
03:01 <c_wraith> Like any sort of for loop that mutates the loop variable in the body, for instance.
03:01 lifter joined
03:01 takle joined
03:01 lifter joined
03:01 <ertes> c_wraith: the pain actually comes from using mutation in IO
03:01 <Cale> It's not that hard -- it's just a pain to use it
03:02 <ertes> and querying mutable variables
03:02 <ertes> C: x < 0
03:02 <c_wraith> I didn't say "hard". I did say "pain" :)
03:02 <ertes> haskell: (< 0) <$> readIORef xRef
03:02 <Cale> Well, I mean, it's not a pain to write the loop construct itself
03:03 <ertes> it's better to have state in terms of either data structures or recursion =)
03:03 <c_wraith> Hmm. I guess I consider the pain of using the construct to be part of the whole process.
03:03 <mbw> About that: I've been thinking. A loop over an array can have several kind of dependencies, like flow dependencies, anti dependencies, another one I forget, and loop-carried dependencies. Only the last one is a "true" dependencies, since others can be removed by throwing more memory at them (i.e. don't write an inplace algorithm, but return a new array). Then, any such loop is convertible to a recursive
03:04 <mbw> function via doing a "reverse tail-call optimization". This tail-recursive function can be expressed via foldl. If I can THEN express this fold via fold/foldMap, is that a formal proof of the absence of a loop-carried dependency?
03:04 <c_wraith> then again, I wrote http://lpaste.net/revision/114261 and I have *no freaking clue* how it works now. Though at least I know what it does.
03:04 fosskers joined
03:04 danharaj joined
03:05 <ertes> mbw: or in other words: the lambda calculus is as expressive as turing machines =)
03:05 <mbw> ertes: Well it was a question. There could be a mistake in my reasoning...
03:05 <mbw> The idea of course being that foldMap could be executed in parallel.
03:06 <ertes> c_wraith: hmm… doesn't look too difficult to me, although parametricity helps a lot
03:06 benjic joined
03:06 <ertes> mbw: i'm not sure about the general case, but (foldMap f) can definitely be evaluated in parallel, *if* f is a monoid morphism
03:06 <c_wraith> ertes: mostly the details. I know I did some weird CPS transform stuff for avoiding unnecessary copying, but I can't explain it now.
03:07 armyriad joined
03:07 <ertes> mbw: (that's the basic idea of MapReduce put in algebraic terms)
03:08 <ertes> indeed, it should be true in general… however, i don't know if your reasoning is correct, because i don't really get it =)
03:08 <mbw> ertes: yeah that's what I was thinking. But it all seems too easy :) Since fold respects monoidal structure, is foldMap f automatically a monoid homomorphism if I have proven that the Monoid created by f is a "real" monoid, i.e. a lawful citizen?
03:09 <ertes> (f a <> f b) <> (f c <> f d) = f a <> (f b <> (f c <> f d))
03:09 stoopkid joined
03:10 <mbw> ertes: What part of my reasoning is unclear?
03:11 ahri joined
03:11 <ertes> i think (foldMap f) is a monoid morphism, if f is a monoid morphism, but it's hard to prove, mostly because the laws are stated so vaguely
03:11 <tswett_to_go> mbw: foldMap f (xs ++ ys) = foldMap f xs `mappend` foldMap f ys, and foldMap f [] = mempty, right?
03:11 <tswett_to_go> That makes it a monoid homomorphism.
03:12 <ertes> tswett_to_go: for lists, yes
03:12 <mbw> Yes, monoids are mapped to monoids basically
03:12 <mbw> Since (++) = mappend for lists.
03:12 <mbw> So this can be generalized in the obvious way.
03:13 <ertes> mbw: the part that isn't clear to me is everything, mostly because i'm not familiar with the terminology =)
03:13 <mbw> (Though I rely on others for these kinds of generalizations, hence my question. I'm too scared of these kind of laws)
03:13 <mbw> Ah.
03:13 <mbw> The dependency stuff.
03:14 <mbw> It's basically the wild west of mutability and the reason that imperative languages struggle with parallelization, or rather proving its correctness.
03:14 peterbecich joined
03:14 peterbec` joined
03:14 <mbw> It's embarrassing really.
03:14 <mbw> Example
03:14 <ertes> hmm… actually i'm not convinced that (foldMap f) is a monoid morphism in general, because weird things happen at infinity
03:14 <mbw> I have to parallelize Fortran programs using Openmp.
03:14 DataComputist joined
03:15 <mbw> There is no open-source tool reliably check for thread races. Even the ones that exist can give false positives.
03:15 <mbw> I can only pray for correctness.
03:15 <ubsan_> mbw: that's why I use Rust ;)
03:15 Rizy joined
03:15 <mbw> Well ok, but I guess with infinity, you can formally proof that foldMap f bottom = bottom or something
03:16 <ertes> that's fine
03:16 <mbw> Fortran programmers are really conservative, unfortunately. The ones I know actually avoid anything newer than Fortran77, since it's probably slower....
03:16 <ubsan_> mbw: that's... insanity
03:16 <ubsan_> have they never seen the C++ talks?!
03:17 <ubsan_> (probably not...)
03:17 <mbw> "c++ is slow because it's object-oriented."
03:17 <ubsan_> zero-cost abstractions + using those abstractions = faster than hand-written
03:17 mizu_no_oto joined
03:18 <ubsan_> yeah... inheritance oriented programming is a blight upon the world
03:18 <mbw> Well to be fair, in conjunction with some commercial compilers, those zero-cost abstractions are still somewhat finicky.
03:18 gpbaran joined
03:18 <ubsan_> thankfully, modern c++ does not use them
03:18 <mbw> The problem lies in the fact that people still don't recognize c++ as a multi-paradigm language.
03:18 <ubsan_> yeah
03:18 <ubsan_> using C++ as Java++ is a bad idea
03:18 <mbw> Resulting in people using that other language, called "C/C++".
03:19 AX3L joined
03:19 <ubsan_> C with classes is nearly as bad
03:19 <mbw> Since every "modern" construct has to be object-oriented, right?
03:19 marcopullo joined
03:19 <ubsan_> maybe if you're from the 1990s...
03:19 <mbw> like I said, fortran77
03:20 <ubsan_> nowadays, it's generics-oriented
03:20 <ubsan_> which is much, much faster
03:20 tromp joined
03:20 <mbw> Yeah but only if implemented via multi-instantiation and not tag-dispatch or type-erasure, which is why generics get a bad rep
03:21 <ubsan_> eugh
03:21 carlosdagos joined
03:24 DataComputist joined
03:27 <nshepperd> generics by code generation has its own problems. more code size -> more cache miss
03:27 <nshepperd> and no polymorphic recursion :(
03:27 <ertes> it's kinda ironic to say something like that in #haskell =)
03:27 begriffs joined
03:28 <mbw> To be fair, I don't use polymorphic recursion in C++ that much :)
03:28 <ertes> mbw: i don't think you use it at all, because C++ doesn't have it ;)
03:28 nomicflux joined
03:29 <mbw> Also, you are free to use the dispatched-based runtime-polymorphism via virtual functions.
03:29 <ertes> RankNTypes doesn't work with C++-style instantiation, i think, unless the compiler learns to instantiate monomorphic functions at use sites
03:30 mizu_no_oto joined
03:30 <ertes> in any case C++ doesn't have it
03:31 sanett joined
03:31 crobbins joined
03:32 <tswett_to_go> This talk of generics by code generation made me wonder if C# lets you write a program that generates infinitely many generic instantiations at runtime.
03:32 Rizy joined
03:32 <tswett_to_go> The answer is yes, totally.
03:32 <nshepperd> there's lots of other great things about c++ though. like affine types! sort of
03:32 <ertes> everything in C++ is "sort of" =)
03:32 DataComputist joined
03:32 <mbw> To be quite frank, even after having come to love haskell, I still would try to avoid recursion in an imperative language, if only for the reason that without something as expressive as pattern matching, it's simply unidiomatic.
03:32 <tswett_to_go> Let me see what Haskell thinks of the same function...
03:32 <ubsan_> ertes: yeah
03:33 <tswett_to_go> :t let wibble x = wibble [x] in wibble
03:33 <lambdabot> error:
03:33 <lambdabot> • Occurs check: cannot construct the infinite type: t3 ~ [t3]
03:33 <lambdabot> Expected type: [t3] -> t2
03:33 <ubsan_> that's why one uses rust! :D
03:33 <nshepperd> mbw: oh yeah, and you can make the stack explode
03:33 <ertes> it has polymorphism, sort of, dependent types, sort of, first-class functions, sort of, …
03:33 <nshepperd> ertes: hah!
03:33 <nshepperd> yeah
03:33 Argue joined
03:33 <tswett_to_go> :t let wibble :: a -> b; wibble x = wibble [x] in wibble
03:33 <lambdabot> a -> b
03:33 <monochrom> There is a mutual cycle between having while-loops and not having pattern matching.
03:33 <tswett_to_go> So you can do it in Haskell, but only with a type signature.
03:33 <mbw> What would be affine types, if I may ask?
03:34 <ertes> mbw: almost linear types
03:34 <nshepperd> mbw: in c++ they call it move semantics
03:34 <ertes> mbw: linear types require exactly one consumer, while affine types allow you to ignore the value
03:35 <tswett_to_go> :t let wibble x = wibble "hello" in wibble
03:35 <lambdabot> [Char] -> t
03:35 <ubsan_> monochrom: Rust :)
03:35 <tswett_to_go> I'm thinking about why the type inference algorithm doesn't infer the more general type for that.
03:36 <ubsan_> ertes: how does C++ not have first class functions?
03:36 <ertes> ubsan_: it has them
03:36 <ertes> sort of
03:36 <mbw> lol
03:36 <ubsan_> I mean, like, what would it have to change to not "sort of" have them
03:36 <monochrom> C++ has 1.5th class functions.
03:36 <c_wraith> C++ has operator()
03:37 <ubsan_> C++ has lambdas
03:37 <c_wraith> which lets you pretend to have first-class functions
03:37 <nshepperd> tswett_to_go: inference for polymorphic functions like 'let wibble x = wibble [x] in wibble' is equivalent to Rank2 inference, I think
03:37 <ubsan_> (or closures, really)
03:37 <mbw> ubsan_ The closest thing to it would in my opinion be std::function, which incurs some overhead. NOT Lambdas, since the type is only known to the compiler.
03:37 <ubsan_> mbw: so your definition of first-class functions is "std::function, but every function type is a std::function"
03:38 <ubsan_> like, otherwise, I have no idea what you're talking about lol
03:38 <tswett_to_go> I guess the inference algorithm must be using a rule like: since wibble is applied to a String, the type of wibble must be of the form String -> t.
03:38 takle joined
03:38 <mbw> I wouldn't really go and "define" anything, since other people are more knowledgable. This is merely stating that lambdas do come with some restriction in c++.
03:39 <tswett_to_go> The fact that this results in a less general type doesn't matter.
03:39 <monochrom> I prefer my fuzzy logic stance of 1.5th class. :)
03:39 <ubsan_> mbw: the fact that lambdas don't have a name for the type is not actually... super... important?
03:39 <ubsan_> like, you can name the type of a specific lambda if you wish
03:39 <monochrom> Or maybe 1.414th class so you can say "hmm that's sqrt(2)"
03:40 <ubsan_> the reason that lambdas don't have normal type names is because of captures
03:40 <nshepperd> tswett_to_go: I don't know the actual details, but I noticed that if you rephrase such a recursive function in terms of a non-polymorphic function and fix, you end up needing a fix at Rank2 type
03:41 <nshepperd> tswett_to_go: to get the more general type
03:41 <ubsan_> without heap allocation, you can't have a lambda that captures these variables, and a different lambda that captures these other variables, and give them the same type
03:41 <monochrom> Or better yet, take a poll over a lot of programmers, "do you consider it 1st class or 2nd class?", then take the average.
03:41 <tswett_to_go> nshepperd: hmm... right. This doesn't work:
03:41 <tswett_to_go> :t fix (\x -> [x])
03:41 <lambdabot> error:
03:41 <lambdabot> • Occurs check: cannot construct the infinite type: t ~ [t]
03:41 <lambdabot> • In the expression: x
03:41 <ubsan_> so unless the argument is that you need implicit heap allocation to have first class functions, I'd argue your argument doesn't stand up ;)
03:42 <mbw> Yes, but a function that expects some function as argument (like std::sort), can do so either via template-parameter, std::function, or function pointer (or those member-function reference thingies). The template parameter does not give you a clue at what kind of function it expects. The function pointer cannot be inlined. std::function makes the type-signature clear (and more readable), bit is the most
03:42 <mbw> inefficient alternative. If you don't care about efficiency, you don't use c++.
03:42 <ubsan_> mbw: so that's more to templates, and their inherent implicitness
03:42 <tswett_to_go> But... I'm trying to think what type signature you could add to that so that it does work.
03:43 <mbw> I uess so.
03:43 <mbw> *gues
03:43 <mbw> :/
03:43 <ertes> ubsan_: try to store a function with a closure in a data structure… there is probably a way, but it's not the usual function pointer way
03:43 <ubsan_> you can always static_assert, or SFINAE, to make it more explicit
03:43 <tswett_to_go> Wait, that was the wrong expression.
03:43 <ertes> ubsan_: generally the type of a function with a closure is a different one from the type of a "regular" function in C++
03:43 <tswett_to_go> :t fix (\f x -> f [x]) -- doesn't work
03:43 <lambdabot> error:
03:43 <lambdabot> • Occurs check: cannot construct the infinite type: t1 ~ [t1]
03:43 <lambdabot> Expected type: [t1] -> t
03:44 <ubsan_> ertes: sure, but you can't solve that without implicit heap allocation anyways
03:44 <mbw> Well ok. But that's not really making things more explicit for the uninitiated.
03:44 <monochrom> tswett_to_go: I think you may like to look up "polymorphic recursion".
03:44 <ertes> ubsan_: right, and that's why C++ has first-class functions, sort of =)
03:44 exferenceBot joined
03:44 <ubsan_> mbw: for the uninitiated, currying makes no sense either ;)
03:44 <mbw> In c++, no.
03:44 <ubsan_> ertes: then I disagree with your definitions of first class functions
03:45 <ubsan_> > Specifically, this means the language supports passing functions as arguments to other functions, returning them as the values from other functions, and assigning them to variables or storing them in data structures.
03:45 <mbw> If you asked me to actually "define" something, making a construct's use feel natural would probably be part of the definition of something begin "first-class".
03:45 <lambdabot> <hint>:1:13: error: parse error on input ‘,’
03:45 <ertes> ubsan_: if you broaden the definition, then suddenly C will also "have first-class functions"
03:45 <ubsan_> ertes: I would argue it does
03:45 <tswett_to_go> :t (fix :: ((forall a. a -> b) -> forall a. a -> b) -> forall a. a -> b) (\f x -> f [x]) -- works???
03:45 <ubsan_> the only issue with C functions is that you can't define them at any scope
03:45 <lambdabot> error:
03:45 <lambdabot> • Couldn't match type ‘a2’ with ‘a1’
03:45 <lambdabot> ‘a2’ is a rigid type variable bound by
03:46 <ubsan_> and of course, in C++, you can, through the use of lambdas
03:46 <mbw> Also, they aren't polymorphic, not even via void pointers.
03:46 <ertes> ubsan_: my definition is that there is a certain type family for functions, functions can be created anywhere, close over variables in scope and all have this particular type
03:46 <mbw> You cannot define a generic map function that takes a unary function as argument in c.
03:46 <ertes> ubsan_: and yes, that inherently requires GC
03:46 <ertes> even unlambda and lazy k have GC
03:46 <ubsan_> ertes: then your definition is bad ;)
03:47 pikajude joined
03:47 skeuomorf joined
03:47 <ertes> ubsan_: my definition is based on logic… free variables are a thing
03:47 tax joined
03:47 gpbaran joined
03:48 <ertes> it would be weird if something that is lexically in scope suddenly goes out of scope… although i'm used to that from my years-long struggle with arrows
03:48 hexagoxel joined
03:49 <ertes> ubsan_: your definition is probably more inspired from the notion of function pointers… but pretty much all languages have those, so your definition is actually quite useless =)
03:49 <mbw> ertes is entirely correct. A lambda in C++ can be converted to a function pointer IFF there is an empty capture clause (since it is then guaranteed to be implemented by a name-mangled run-of-the-mill function). Otherwise, a function object is created. But I don't think this warrants GC. Maybe I misunderstood?
03:50 <mbw> (capture clauses let you associate free variables as copy or reference with a lambda).
03:50 <ubsan_> oh, also, you can use `function_ref`, if you don't want overhead in your `std::function`
03:50 <ubsan_> ertes: I don't like garbage collection
03:51 <ubsan_> any definition which says "garbage collection is implicit overhead, so it's fine, but explicit overhead is not", doesn't sit right with me
03:51 <ertes> ubsan_: i do like it, because it generally does a better job than me at managing memory, because it can come up with cleverer reuse plans
03:51 <mbw> Just take it like what it is. A useful abstraction. I don't like memory leaks either.
03:51 <ertes> GC is not "overhead", it's a memory management scheme
03:51 <nshepperd> tswett_to_go: hm, I managed to do it but only by hiding the polymorphic bit in a newtype
03:52 <ubsan_> ertes: you can say that, but then you might wonder why linear typing is a thing ;)
03:52 <ubsan_> (hint: it's because GC is implicit overhead)
03:52 <Cale> That also isn't true
03:53 <ertes> ubsan_: linear typing would be useful in a language like haskell in order to use in-place updates for things like arrays
03:53 <ertes> not for better-informed GC, because GHC's GC is very well informed
03:53 <ertes> it doesn't need the help of linear types =)
03:53 <ubsan_> ertes: with linear types, a GC no longer needs to exist
03:53 fabianhu joined
03:53 <Cale> Huh?
03:53 <ubsan_> this is why C++ and Rust are so fast
03:53 <ertes> ubsan_: that's wrong
03:54 <ertes> ubsan_: it's still GC, but with a certain guarantee
03:54 <ubsan_> ertes: emm... no it isn't?
03:54 <mbw> Please let's not go down that road. Languages aren't fast (though I guess Italian is?)...
03:54 <ubsan_> scope-based resource management is not GC
03:54 <ertes> ubsan_: we could argue about the definition of GC, but it doesn't necessarily involve a heap and algorithms
03:55 <Cale> I suppose if you had a very annoying language in which every variable had to be linear, so you could never use anything more than once, you could avoid the need for a GC.
03:55 <ertes> ubsan_: you know how you use recursion in haskell to write something stateful? GC is happening there on a very small scale
03:55 <ubsan_> Cale: just look at Rust or C++. They don't need a GC, because they have affine variables
03:55 <mbw> That doesn't make sense.
03:55 <ertes> ubsan_: but the resulting program may not use any heap memory or actual GC algorithms… it's much more likely to do an in-place update
03:56 <ertes> and that's still GC, just very smart GC
03:56 <ubsan_> mbw: it's a really simple concept
03:56 <mbw> If this is about move semantics, shouldn't C++ have had garbage collection before c++11!?
03:56 <ertes> GC is not a library, it's a compiler feature
03:56 <nshepperd> I wouldn't describe what happens when a unique_ptr goes out of scope as 'garbage collection'
03:56 <ubsan_> I'm not sure how it doesn't make sense
03:56 <ubsan_> mbw: you can replace garbage collection in other ways
03:56 <ubsan_> like manual memory management
03:56 <Cale> ubsan: Last I checked, you could use variables more than once in those languages.
03:56 <ubsan_> or copy semantics
03:56 <mbw> Then I guess the concept of an affine variable still isn't clear to me.
03:57 <ertes> ubsan_: i think you have a major misconception on what GC is
03:57 <Cale> mbw: Certainly, how ubsan is using the word is unclear...
03:57 mmachenry joined
03:57 <ubsan_> ertes: tracing GC
03:57 <ubsan_> what people mean when they say "GC"
03:57 <ubsan_> like what Haskell uses
03:57 <ertes> ubsan_: only for certain long-lived values
03:57 <ertes> like values stored in data structures
03:58 <ubsan_> ertes: there are very clear definitions for what a GC is
03:58 <ubsan_> SBRM is not one of them
03:58 <ubsan_> mbw: go use Rust then?
03:58 <ertes> ubsan_: example: f x = print x >> f (x + 1)
03:58 <ertes> ubsan_: does this use GC?
03:58 <ubsan_> ertes: I don't know, it depends on the implementation
03:59 <ubsan_> probably, because Haskell is box-happy
03:59 <mbw> Depends on whether it's used, first of things.
03:59 <ubsan_> true
03:59 Ayey_ joined
03:59 <ubsan_> this is a very weird argument path that y'all are traveling down
03:59 <ertes> ubsan_: it does in haskell, yet it compiles to a tight loop that updates in-place
04:00 <c_wraith> I'd be surprised if that allocates when compiled with optimizations
04:00 <Cale> Also probably depends on the type of x
04:00 <Cale> yeah
04:00 <ertes> no allocations at all, but it still uses "GC", because it's not me managing the memory, it's GHC
04:00 <c_wraith> in fact, I've used loops like that to prevent the garbage collector from running. :)
04:00 <ubsan_> "GC sometimes doesn't happen, therefore... something"
04:00 <mbw> On the other hand, are you sure of that? After all, things like the "forM_ [1..] - bug" still aren't fixed...
04:01 <ubsan_> debate through confusion?
04:01 <ubsan_> this is a very strange tactic
04:01 <ertes> well, ok, it probably defaults to Integer, which will need allocation at some point
04:01 <ertes> but the universe will have collapsed before that happens =)
04:01 <Cale> I don't even know what is being debated here, exactly.
04:01 <ubsan_> Cale: honestly, I don't either
04:01 <ubsan_> I stated that linear types could be used to replace GC
04:01 <ertes> well, it's about linear types as a memory guarantee
04:02 <ubsan_> as seen in the affine replacements for GC seen in Rust and C++
04:02 <Cale> ubsan_: Well, I think that's pretty untrue -- you'll still want a GC to pick up things which aren't linear -- making everything linear is unreasonable.
04:02 <ertes> it's still GC to me, because there is no manual memory management, unless you consider the final consumer to be "explicit freeing"
04:02 <ubsan_> (noting that, of course, C++ doesn't have true affine types, but a fairly okay approximation)
04:02 <ubsan_> Cale: linearity + references = awesome
04:03 <ubsan_> ertes: but it's not GC
04:03 <nshepperd> ertes: you're arguing that c++ has a GC...?
04:03 <ubsan_> it's RAII
04:03 <Cale> ubsan_: Well, you *could* make everything linear, but that would come at the expense of Turing completeness, for example.
04:03 <ubsan_> Cale: that's why Copy types are a thing
04:03 <mbw> nshepperd: Actually, it does have an official ABI for implementing GC I think.
04:03 <nshepperd> anyway some things certainly do need to not be linear
04:03 <Cale> ubsan_: So then how do you clean those up?
04:03 <ubsan_> also, linear things are most definitely turing complete
04:03 <ertes> nshepperd: well, in a sense it does: each time you return from a function, the stack frame is freed for you =)
04:03 <nshepperd> like some fancy tree based data structures
04:04 <ubsan_> mbw: yes, it does. nobody has ever used it
04:04 <ubsan_> the boehm people wanted it to be added to the standard
04:04 <Cale> ubsan_: If everything must be used exactly once?
04:04 <ertes> anyway, i would like to have uniqueness types in haskell, not as an efficiency-related guarantee, but as a way to have a nicer interface to mutable arrays
04:04 <ubsan_> Cale: yeah
04:04 <Cale> ubsan_: How do you write a fixpoint combinator?
04:04 <ubsan_> :t fix
04:04 <lambdabot> (a -> a) -> a
04:05 <mbw> This all sounds like it would read like SSA compiler output...
04:05 <Cale> ubsan_: That's usually going to use its argument more than once. :P
04:05 <ertes> the rust people chose to have affine types, we chose to have a smart compiler =)
04:05 <ubsan_> Cale: I don't know. I've never tried to implement it.
04:06 <ubsan_> ertes: and you can see the difference in speed ;)
04:06 <ertes> ubsan_: can i? my haskell code is pretty fast
04:06 <ubsan_> ertes: pretty fast != as fast as C, C++, and Rust
04:06 <MarcelineVQ> why not
04:07 <ubsan_> because it isn't
04:07 <MarcelineVQ> oh
04:07 <mbw> lol
04:07 <ertes> ubsan_: i'd challenge that, and in fact i've written code that ran faster than the equivalent code in C, compiled both with GCC and clang
04:07 safe joined
04:07 <mbw> :t absurd
04:07 <lambdabot> Void -> a
04:07 <ubsan_> ertes: I'd like to see that code
04:07 <Cale> ubsan_: If you only have linear typed variables, then the amount of stuff you have never changes.
04:07 <ertes> ubsan_: http://lpaste.net/101980
04:07 <ubsan_> and I'd like to see the C compared to
04:07 <Cale> Your program runs in constant space, hooray!
04:07 <ertes> ubsan_: everything is linked from there
04:07 <ubsan_> Cale: there's actually this really great paper about this
04:08 <ubsan_> "The Computational Content of Isomorphisms"
04:08 <ubsan_> I haven't gotten to the part where they prove turing completeness, but apparently they do at some point
04:08 <Cale> Sometimes constant space is good enough
04:08 <ertes> ubsan_: the thing that makes haskell code slow is mostly the wrong choice in data structures and a somewhat unfortunate base library (with String as the default, etc.)
04:09 <ertes> ubsan_: but you can avoid all those things: choose the right data structures and use ByteString/Text/Vector/…
04:09 <Cale> But usually people like to introduce something which allows unrestricted duplication of a resource
04:09 eazar001 joined
04:09 <ertes> in particular: FP is NOT about using lists for everything
04:09 <Cale> and as soon as you have that, ordinary lambda calculus embeds into your type theory
04:09 <Cale> (just stick that annotation on everything in sight)
04:10 <ubsan_> ertes: see, that does not look like haskell lol
04:10 <ertes> ubsan_: why not?
04:10 <ubsan_> Cale: you can do that
04:10 <Cale> What doesn't look like Haskell?
04:10 <ubsan_> but I find it more interesting to embed them in arrows :3
04:10 <Cale> ubsan_: Well, my point is, you have all the same reasons to want a GC for a linear type system as you do for plain lambda calculus.
04:11 <Cale> (so long as you have that unrestricted duplication operator)
04:11 <ubsan_> Cale: yeah, but you don't need it
04:11 <Cale> huh?
04:11 <ubsan_> you can embed it in arrows
04:11 Argue_ joined
04:11 <Cale> You don't need a GC for plain lambda calculus either
04:11 <ubsan_> that's the point of the paper
04:11 <Cale> You can just never deallocate anything
04:11 <Cale> problem solved
04:11 <ubsan_> ...
04:11 <ubsan_> w/e
04:11 <ubsan_> read the paper
04:11 <Cale> I guess
04:12 <ubsan_> ertes: to be fair, your short names do not help
04:12 <Cale> I don't think substructural type systems magically absolve you of the problem of managing memory in the real world.
04:12 <ubsan_> it's nearly impossible to read your code
04:12 <ubsan_> Cale: that's why you use RAII
04:12 <ubsan_> it not only solves memory management, it also solves resource management in the general case
04:13 <nshepperd> I don't know about this 'embedding in arrows' stuff, but making *everything* linear seems one cross too much to bear
04:13 yianni joined
04:13 <nshepperd> you'll pry my persistent data structures from my cold dead hands
04:13 <ubsan_> nshepperd: I mostly think it's cool
04:13 <Cale> nshepperd: Yeah, you need to know up front how much stuff you'll need
04:13 <ubsan_> I wouldn't argue to actually do everything with it
04:13 <mbw> I find it reasonably readable.
04:14 <ubsan_> ertes: you know you can factor stuff out into functions, right?
04:14 <ertes> ubsan_: i'm happy to explain them, if you ask which ones
04:14 <ertes> ubsan_: i think i did
04:14 <ertes> they're just not at the top level
04:14 <ubsan_> oh, I guess os
04:14 <ubsan_> *so
04:14 <ubsan_> I'm not the best at reading haskell
04:14 <ubsan_> alright, wbits1
04:14 <ubsan_> and wlog
04:14 <ubsan_> what do they do?
04:15 <ertes> > bitSize (undefined :: Word) - 1
04:15 <lambdabot> 63
04:15 <ubsan_> and what's this: `[e| b |]`
04:15 <ertes> number of bits in a Word - 1
04:15 <ertes> a Word has 2^6 = 64 bits
04:15 <ertes> wlog = 6
04:15 <ubsan_> ah, okay
04:16 <ubsan_> what's the [e| b |] thingy
04:16 <ertes> i could have used Word64, but i wanted it to run faster than the equivalent C on 32-bit architectures as well =)
04:16 <ubsan_> so this doesn't use infinite precision
04:16 <ubsan_> okay
04:16 <ertes> that one is template haskell syntax… it was necessary at that point to make GHC evaluate it at compile time
04:16 <ertes> it's a static value
04:16 Cxom joined
04:16 <ubsan_> what's this `arr <- Vsm.replicate (maxW + 1) (-1 :: Word)`
04:17 <Cale> That makes a vector consisting of maxW + 1 copies of -1
04:17 <ubsan_> is that just allocating an array of size maxW + 1, and filling it with -1s
04:17 <mbw> Seems to allocate an array
04:17 takle joined
04:17 <ertes> yeah
04:17 <mbw> This is all fairly idiomatic.
04:17 sanett joined
04:17 <ertes> it's imperative, of course, but not in any way not "like haskell" =)
04:17 <Cale> Well, as idiomatic as something which does a bunch of bit hackery can be, anyway
04:18 <ubsan_> what's the C version
04:18 <MarcelineVQ> it's in the paste
04:18 <ertes> ubsan_: http://lpaste.net/101507
04:18 <ertes> look at the bottom
04:18 <ubsan_> oh, cool
04:19 Maxdamantus joined
04:19 <ubsan_> I wonder what the equivalent C++ implementation would be in terms of speed
04:20 <ertes> probably the same as the C version
04:20 <Cale> I wish dons' entire life were not consumed by his job
04:20 <mbw> no march=native
04:20 <Cale> He used to keep up the Haskell microbenchmarks on the shootouts
04:21 <ertes> i've also verified that GCC's output does in fact use proper bit operations
04:21 <Cale> and got Haskell basically to the top of the charts constantly :D
04:21 s4kashya3 joined
04:21 cschneid_ joined
04:21 <ertes> and it was still slower… not by much, but slower =)
04:21 <Cale> (And that's why we have stuff like ByteString now)
04:21 <ertes> my explanation is that GHC is very good at reusing memory statically
04:21 carlosdagos joined
04:22 <mbw> There should be a way to use some intrinsics, if you're good at that.
04:22 <mbw> Though that's not vanilla C.
04:22 <ertes> mbw: i did actually test that, and it didn't make a difference (it's x86_64 anyway)
04:22 <ertes> mbw: it might make a difference on i386, if you're allowed to use some of the i686 instructions
04:23 Guest_ joined
04:24 knx32542 joined
04:24 <ubsan_> see, this is why I use C++: https://gist.github.com/ubsan/a771eb2ffeb4f13c854304e2b061ef5b
04:24 <ubsan_> it's by far the most readable of the three implementations
04:24 <Cale> ubsan: Does it perform the same?
04:25 <ubsan_> Cale: no idea, haven't tested it yet
04:25 <ubsan_> oh, wait, that's a static array
04:25 <ertes> ubsan_: of course… i could have used on of the bit-vector libraries for that
04:25 <ertes> the 'vector' library has the unfortunate habit of representing a (Vector Bool) using a whole byte for each bit
04:26 <Cale> ertes: Did you try a version which used IOUArray of Bool?
04:26 <ubsan_> "unfortunate"
04:26 <ertes> Cale: yes, it was slightly slower
04:26 <Cale> Ah, possibly more readable though :)
04:26 <ertes> most likely due to index arithmetic
04:26 <Cale> ertes: iirc, IOUArray does the bit packing for you
04:26 <ertes> yes, but the point of this was to win against C =)
04:26 <Cale> right
04:26 <ertes> yes, it does
04:27 knx32542 left
04:27 <ertes> Vector should do it, too… i have no idea why it doesn't
04:27 <Cale> Yeah, hm
04:27 <ertes> perhaps that would be worth a pull-request some day
04:27 <Cale> I'm sure it would
04:28 doodlehaus joined
04:28 <ertes> at that point (it's from a time when GHC 7.6 was fresh) there was one library on hackage that provided a Bit type with corresponding vector instances
04:28 <mbw> ubsan_: Do literals like const auto i = size_t(1000) work out as they should? This seems kinda weird to me, why not size_t i = 1000/1000ul or use decltype?
04:29 <ertes> but despite being more compact, it performed way worse than this manual method
04:29 cschneid_ joined
04:29 <ubsan_> mbw: because auto is far more readable
04:29 <ertes> not just slightly worse the way IOUArray did, but *much* worse
04:29 <Cale> hm
04:29 <ertes> i think, it was this one: https://hackage.haskell.org/package/bitvec
04:30 <ertes> but there have been new releases since, so james may have fixed it
04:30 mbw_ joined
04:30 <ertes> mokus_: ^ (if you're interested)
04:31 <nshepperd_> auto i = size_t(2) is more readable than size_t i = 2?
04:32 <ubsan_> haha
04:32 <ubsan_> nice
04:32 <ubsan_> the bitset is too big for the stack, so it segfaults
04:32 <ubsan_> nshepperd_: um, yeah
04:32 <ertes> ubsan_: to conclude, GHC-haskell is not really slower than C/C++/rust, but there seems to be a lot of incentive not to use the best tool for the job
04:32 <ubsan_> ertes: honestly, if you're writing code like that, just write C++
04:32 <ertes> and sometimes i feel like a broken jukebox when the topic of data structures comes up in #haskell
04:33 <ertes> "do not use lists here"
04:33 <ubsan_> if you're writing code that actually looks nice in Haskell, it's going to be slower than nice code in C++ and Rust
04:33 <ubsan_> it's all a question of defaults
04:33 <Cale> Well, using lists inappropriately is common because (I think correctly) they're the first thing we teach to beginners.
04:33 <ertes> ubsan_: why? i'm still taking advantage of haskell… not necessarily in this small example, but in larger code i definitely do
04:33 <ubsan_> ertes: this is your example, though
04:34 <ubsan_> maybe I was wrong about not using haskell because it's not fast
04:34 <ubsan_> maybe I shouldn't use haskell because it's ugly
04:34 <Cale> and of course, you always have to weigh developer time vs. program time
04:34 <ubsan_> that's what I get from this sample ;)
04:34 <Cale> Stuff like Data.Map is so often good enough that it's not even funny :)
04:34 <ertes> ubsan_: it's ugly, because i'm doing all the bit-twiddling by hand… and that can be fixed (by fixing the vector library)
04:35 <ertes> ubsan_: i just don't use bit vectors that much in practice, so i haven't contributed that particular patch yet =)
04:35 hexagoxel joined
04:35 <ubsan_> ertes: look, I don't care if haskell can be as fast as C++ or Rust
04:35 <Cale> and of course, if we wanted to micro-optimise everything, we could replace individual uses of Data.Map with something trickier and more carefully selected
04:35 otto_s joined
04:35 <ubsan_> I care if pretty haskell can be as fast as C++ or Rust
04:35 <ertes> ubsan_: yes, it can
04:35 <ubsan_> because I don't want to write like that
04:36 <Cale> ubsan_: The important thing which can't be appreciated through microbenchmarks is how things work out in the large
04:36 <ertes> ubsan_: this code is not representative of code beauty, although it is beautiful *for what it does*
04:36 <Cale> ubsan_: In the large, C++ programs are unmaintainable shit compared to Haskell programs.
04:36 <kadoban> I've spent a decent amount of time trying to write fast haskell for various uses. It's pretty easy to get within 2x or so of C++ speed. I usually don't have to go beyond that.
04:37 <ubsan_> Cale: you say that, but it's not really true anymore
04:37 <ubsan_> you're no longer up against C++03
04:37 <Cale> It will always be true
04:37 <ubsan_> you're up against C++14
04:37 <ubsan_> okay, whatever opinion floats your boat
04:37 <ertes> ubsan_: one thing that is really nice about haskell (and it shares that property with C++ to some degree): free abstractions
04:37 <ubsan_> ertes: I've seen very little evidence of that
04:37 <Cale> Well, until C++ is unrecognisably different
04:37 <kadoban> ubsan_: There have been improvements, but it's still the same language it always was.
04:37 <ertes> free as in free bear, not free monad
04:37 <ertes> beer
04:37 <Cale> to the point that you're not going to want to call it C++ :)
04:37 danharaj joined
04:38 <ubsan_> Cale: C++11 is a superset of C++03 as C++ is a superset of C
04:38 <ubsan_> it is basically a completely different language
04:38 <Cale> The things about C++ which have to change in order to make my complaints go away are pretty foundational in nature.
04:38 <ertes> ubsan_: the problem is that no example i could provide will satisfy you
04:38 <ubsan_> ertes: probably not
04:38 <kadoban> ubsan_: Those two lines you just typed seem pretty contradictory.
04:39 <ubsan_> kadoban: C++ is a completely different language from C, despite being mostly a superset
04:39 <ubsan_> added abstraction power means a lot
04:39 <ertes> ubsan_: i don't want to say that you're suffering from the blub paradox, but at this point i can only ask you to trust me that GHC produces very efficient code for idiomatic haskell
04:39 harfangk joined
04:40 <ubsan_> ertes: I don't though. there's so much evidence against it
04:40 <ertes> ubsan_: is there?
04:40 <kadoban> ubsan_: Really? What evidence?
04:40 <mbw_> How dare you!
04:41 <Cale> You *really* want a garbage collector managing memory *most* of the time. Sure there are cases where you'd rather be careful and ensure that you're not allocating, or are carefully controlling allocation, but doing it everywhere just for the sake of the 1% of cases where it matters just spoils your ability to reason about things, ruins compositionality in various ways, and is just generally a waste of time.
04:41 <Cale> (programmer time, which is expensive)
04:41 takle joined
04:42 <ertes> and i say it again: GHC is smart enough that manual memory management (you can do it) rarely pays off
04:42 eduardm joined
04:43 louispan joined
04:43 <ubsan_> ertes: there's a lot of benchmarks online, showing that C++ is faster than haskell
04:43 <nshepperd> micro optimization mostly doesn't matter outside of the inner loop anyway...
04:43 <nshepperd> use the right algorithm first
04:43 <Cale> Nevermind that you also *really* want equational reasoning
04:43 <ubsan_> the only benchmarks I've seen where Haskell is as fast as C or C++, is benchmarks where it's either unidiomatic (or unobvious) haskell (see, yours)
04:44 <ubsan_> or unidiomatic C, like http://lambda.jstolarek.com/2013/04/haskell-as-fast-as-c-a-case-study/
04:44 <ertes> ubsan_: it's easy enough to find just the right problem that GCC is better at than GHC
04:44 <ertes> ubsan_: except those aren't the problems i need to solve in practice
04:44 <ertes> microbenchmarks are mostly useless
04:44 <mbw> This. Even if I have to foreign call critical functions, the purity aspect, along with "safe" program transformations is way more important. Make it correct, first.
04:45 <mbw> (With _this_ being what Cale said.)
04:45 <ubsan_> I'd rather have lifetimes and ownership
04:45 <ertes> well, i'm more the kind of person who will solve correctness *and* efficiency at once
04:45 <Cale> The microbenchmarks are only useful in that they're able to show that in the small, you can make things really fast or really space-efficient when pressed.
04:45 <ertes> because retrofitting efficiency is actually surprisingly difficult
04:45 <Cale> They don't give any sense of the more important goal: maintainability of large projects.
04:45 <ubsan_> and retrofitting correctness is even harder
04:46 <ertes> i get correctness mostly from the way i solve problems in haskell anyway, so i can focus on efficiency right away
04:46 <Cale> It's maintainability of large projects and especially team efforts where Haskell really begins to shine.
04:46 <ubsan_> Cale: looking at LLVM or servo, I'd argue that C++ and Rust also shine quite brightly there
04:46 <ertes> and for the difficult stuff i can always write a test suite
04:46 <mbw> Also, the stuff where C/C++ programs have been really optimized is making heave use of vector intrinsics, cache-line and register blocking, and all that other good stuff. Do you do that on a daily basis?
04:47 <ertes> in any case correctness has never been a real problem to me since i switched to haskell… but efficiency is, and i will admit one thing: it takes a bit of experience to come up with efficient code in haskell
04:47 <ertes> but i don't think it's any different in other languages
04:47 <Cale> ubsan_: Haskell's type system and referential transparency give it so many advantages over these.
04:47 <ubsan_> Cale: lifetimes and ownership
04:48 <ubsan_> lifetimes, and ownership
04:48 <Cale> First of all, in terms of being able to understand quickly how to use other people's code
04:48 gpbaran joined
04:48 <ubsan_> (and besides, Rust is basically referentially transparent)
04:48 <Cale> "basically" isn't good enough ;)
04:48 <ubsan_> yeah, it is
04:48 <ubsan_> lol
04:48 <mbw> So I guess we did "go there", after all :(
04:49 <ubsan_> the only things you can change are implementation details which you shouldn't be able to see
04:49 <ertes> ubsan_: lifetimes and ownership are actually easy in haskell
04:49 <ubsan_> for example, a function which takes a `T: Clone` can optimize for `T: Copy`
04:49 <ertes> you need to understand sharing, but if you do, then you have a pretty clear idea where your values are and when they will cease to exist
04:49 <ertes> (and you really need to understand sharing in haskell)
04:49 <Cale> But it's really hard to explain what I mean with small examples.
04:50 takle joined
04:50 sanett joined
04:50 <Cale> Only experience can really be convincing here, I think.
04:50 <Cale> (because all the most convincing examples involve programs which are large)
04:50 Tharbakim joined
04:51 <ertes> example: let f x' = \y -> x + y where x = x'^100000000 in map (f 3) [1..10]
04:51 <nshepperd> ubsan_: er, lifetimes and ownership are only one feature
04:51 <Cale> I can give anecdotes, but I'm not sure how convinced you ought to be by them
04:51 <ertes> i *know* that 3^100000000 will be computed only once
04:51 <ertes> and will go away after the map
04:51 <nshepperd> there are lots of activities one needs to do in programming apart from managing resources O_O
04:51 <Cale> yes
04:52 <ubsan_> ertes: I'd rather it be brought explicitly into the typesystem
04:52 <nshepperd> anyway, I think we've probably had enough programing language wars for one night?
04:52 pita joined
04:52 <ertes> yeah, i agree
04:52 <ubsan_> damnit, I do not understand bash
04:53 <Cale> If our programs only did a bunch of allocation and deallocation of memory, and didn't do anything very complicated aside from that, perhaps we would all be crazy to be arguing with ubsan_
04:53 <ubsan_> Cale: I'd argue you're far more crazy to be arguing with me *because* your programs do a lot more
04:53 zennist joined
04:54 <Cale> I don't have time to give a shit about memory management 99% of the time.
04:54 <monochrom> The huge overhead of crossing FFI barriers is why you would use a high-maintenance language for the whole program even though you just need its fine-control for just 1% of the whole program.
04:54 Xanather joined
04:54 <Cale> and the remainder of cases are not so hard to deal with, but I don't want to be wasting time that could otherwise be spent actually delivering meaningful value to the client on that.
04:55 <ubsan_> Cale: ...right
04:55 <ubsan_> exactly
04:55 FreeBirdLjj joined
04:55 <Cale> So that's why I program in Haskell
04:55 <nshepperd> haskell's (or is it GHC's?) ffi is so awesome <3
04:55 <ubsan_> GC and C are not the only two choices~
04:55 raycoll joined
04:55 <kadoban> monochrom: Is there actually a huge overhead in that? (or was that sarcasm?)
04:55 <Cale> Because it optimises the 99% case
04:55 <ertes> nshepperd: i'd say it's good enough… i prefer not to have to use it
04:55 <monochrom> It is a huge overhead. I'm serious.
04:56 <mbw> Like, totally serious?
04:56 <ertes> nshepperd: to such an extent that i will rewrite C libraries in haskell
04:56 <Cale> (and doesn't screw us in the 1% case)
04:57 <ertes> hsc2hs helps a lot, but it comes with its own problems… so far i haven't solved the interactive development problem
04:57 <monochrom> If you just need to cross the boundary once every 2 seconds, it's OK, that is no big deal.
04:57 <ertes> which is, BTW, one of the most important reasons for me not to use C++ or rust: interactive development
04:57 takle joined
04:57 <kadoban> It's pretty much when you need to do it in a "tight loop" I suppose?
04:58 <ubsan_> so, 792 msec, over 100 trials, for the idiomatic C++ version
04:58 <monochrom> But good luck with "the innermost loop makes an FFI call per iteration, just so to call a machine-code subroutine that runs for 10 clock cycles"
04:58 <Cale> ubsan: and the other versions?
04:58 <ertes> ubsan_: what about my C code?
04:58 <kadoban> Ah. Yeah that I'm not surprised is a bad idea.
04:58 <ubsan_> ertes: I haven't tried them yet
04:58 <ubsan_> one sec
04:59 <nshepperd> hopefully you're not calling the FFI in your inner loop, because the FFI function *is* the inner loop
04:59 <ertes> ubsan_: remember that the timings in the paste are from 2014 =)
04:59 <monochrom> So that means you will want the whole innermost loop to be written in machine code. But then maybe the innermost loop has to worry about memory management and I/O and this and that... Now all your Haskell benefits go down the drain.
04:59 <ubsan_> emm
04:59 <ubsan_> I think I have an off-by-two error?
05:00 <ertes> ubsan_: my code produces the correct result, based on a comparison with what PARI/GP says
05:00 <ubsan_> ertes: yeah, I'm not sure what's wrong
05:00 <mbw> monochrom: But if it does syscalls, I/O and the like, this will be the bottle-neck anyway.
05:00 <ertes> ubsan_: did you initialise the first two bits?
05:01 <ertes> ah, nevermind
05:01 <ubsan_> ertes: https://gist.github.com/ubsan/a771eb2ffeb4f13c854304e2b061ef5b
05:01 <ertes> you skip them anyway
05:01 <monochrom> Some basically I'm saying the possibility (hopefully you aren't that unlucky) that the 1% of your program that needs fine-control is highly infectious in terms of dictating what language you end up using. It can spread.
05:01 <ubsan_> oh, I see what we did
05:01 <ubsan_> I include 1, and you don't include 2
05:01 <ubsan_> I think?
05:01 <ubsan_> well, I do include 1
05:02 <ubsan_> oh yeah, you didn't include 2
05:03 <ubsan_> I see what's happening
05:03 <* ubsan_> fixes
05:03 <mbw> Ok, but I thought we were all aware that the situation "call this one computation-heavy loop with 1e20 iterations via FFI and all is good" exists only in theory.
05:03 <ertes> ubsan_: hmm? i think i do include 2
05:03 <ubsan_> ertes: I was including both 0 and 1
05:04 <ertes> ubsan_: are you sure? i don't see that
05:04 <ertes> ah, yes
05:04 {emptyset} joined
05:04 <ertes> you're using array.count()
05:04 <ertes> in that case you need to initialise the first two bits to 0 explicitly
05:04 <ertes> ubsan_: that has to be slower than my version, because you're doing an extra iteration at the end
05:05 takle joined
05:05 <ubsan_> ertes: yeah
05:05 <nshepperd> mbw: usually I have more like 1e5 iterations
05:05 <nshepperd> a respectable loop
05:05 <ubsan_> about 45 msec difference
05:06 <ertes> ubsan_: i would expect the bool-vector version to be on par with my C version
05:06 Rainb joined
05:06 <ertes> mostly do to aggressive inlining
05:06 <ertes> *due
05:07 <ertes> also remember that i used -O3 -funroll-loops, which gave it a *major* speed boost
05:07 <ubsan_> ertes: without the extra loops, it's 32 msec faster
05:07 <ubsan_> err, extra loop
05:08 <ubsan_> it's 4 msec faster with -funroll-loops
05:08 <mbw> Was it -O3 or -funroll-loops or both that gave the speed-up? I remember reading something on Agner's site in which he recommended not to unroll loops on newer cpus with uop caches.
05:09 <ubsan_> with -funroll-loops, they're the same
05:09 <ertes> mbw: both… it was on an i5, but i can no longer tell which one
05:09 <mbw> But that was last year and probably referring to knight
05:09 <ubsan_> 785 msec per loop
05:09 <ertes> it was already a few years old at that point
05:09 <ertes> so -funroll-loops may indeed be harmful on newer CPUs
05:10 <ubsan_> > Failed to load interface for ‘Data.Vector.Storable.Mutable’
05:10 <lambdabot> <hint>:1:30: error: lexical error at character '\8216'
05:10 <mbw> It's probably not a b&w thing, anyway.
05:10 <ubsan_> ertes: ?
05:10 <ertes> ubsan_: you need the 'vector' library
05:10 <Cale> ubsan_: Have to install the vector package
05:10 <ertes> ubsan_: go into a new directory and type: cabal sandbox init
05:10 <mbw> It's only Data.Array that ships with GHC.
05:10 <* monochrom> cringes. The world is getting exciting. Unrolling loops can be slower?! What has the world come to?!
05:10 <ertes> ubsan_: then (in the same directory): cabal install vector
05:11 <Cale> monochrom: haha
05:11 <mbw> I probably should look for the link to back that up :)
05:11 <monochrom> Next you're going to tell me procedure calls are cheaper than gotos.
05:11 <ertes> ubsan_: then use the following command: cabal exec ghc -O2 …
05:11 mk-fg joined
05:11 mk-fg joined
05:12 <ubsan_> I'll also do this same thing with Rust
05:12 <ertes> ubsan_: when you're done, you can just delete that directory, and everything will go away
05:12 <ubsan_> ertes: nice
05:12 <ubsan_> although I wish every language had cargo
05:12 <ertes> that's GC for you =P
05:12 <ubsan_> that is *so* manual memory management :P
05:12 <ertes> ubsan_: if you want it to be actual GC, use nix instead of cabal-install =)
05:13 <ubsan_> ertes: ugh, nix -.-
05:13 <ertes> but i don't want to impose another learning curve on you ;)
05:13 <ubsan_> nix is very weirdly popular in the rust community
05:13 <Cale> Nix is amazing when you have other people around to configure it on your behalf.
05:13 <monochrom> heh
05:13 <ubsan_> lol
05:14 <mbw> here: http://www.agner.org/optimize/blog/read.php?i=165
05:14 <monochrom> I guess we still need to hire sysadmins.
05:14 <Cale> I couldn't use it for my personal machines though
05:14 <Cale> But it's really nice for work projects
05:14 <mbw> A more general treatment is given here:http://www.agner.org/optimize/microarchitecture.pdf . It basically just boils down to not unrolling unnecessarily.
05:14 bondan joined
05:14 <ertes> well, nix is just a magical experience, literally… every machine i come in contact with suddenly has a /nix directory appearing out of nowhere
05:15 <Cale> Never having to worry about whether I have the right versions of things, having super easy automated deployments to AWS, and so on.
05:15 <ertes> it's also nice for personal things… if only not to have to be root to install stuff
05:15 <ubsan_> ertes: that's why I use brew ;)
05:15 <ertes> but it really shines for development and deployment
05:16 <ubsan_> but also, -fllvm is being annoying
05:16 <ertes> ubsan_: take brew, generalise it to *everything*, add a bunch of handy features, and you have nix… and a life-long learning curve to climb =)
05:16 <ubsan_> ertes: yeah, yeah, I've gotten the sales pitch
05:16 <Cale> Nix' language should just be Haskell
05:17 <Cale> Here's what the plan should be:
05:17 <ubsan_> why doesn't ghc work with llvm 3.8 :[
05:17 <mbw> So basically it's about as complex as git, and people use 1% of it?
05:17 <Cale> 1) Write a Haskell combinator library which does the same thing as Nix.
05:18 <ertes> ubsan_: usually when i get a message like that i interpret it as: "dude, update your GHC already!"… and usually my interpretation is correct =)
05:18 <Cale> 2) Write an interpreter/compiler for Nix expressions which translates them into the Haskell combinator library and allows .nix files to be used.
05:18 <Cale> 3) Gradually port nixpkgs.
05:18 cschneid_ joined
05:18 kottt joined
05:18 <ubsan_> ertes: without -fllvm, it's .3 seconds slower
05:18 <ertes> Cale: unfortunately nix has magic
05:18 <mbw> ertes: No, the newest GHC also only supports 3.7 iirc.
05:18 <ertes> Cale: and nixpkgs uses that magic
05:18 <ubsan_> I don't feel like dealing with llvm + ghc things right now
05:18 <Cale> What do you mean by magic?
05:18 <ubsan_> ertes: could you do it for me?
05:19 <ertes> Cale: stuff you would need TH for
05:19 <tswett_to_go> I've been pondering the idea of making Haskell code callable from .NET code. There are two "obvious" ways to do it.
05:19 <ertes> Cale: like callPackage
05:19 <ertes> ubsan_: let me check
05:19 <tswett_to_go> One, compile the Haskell into .NET IL. Two, compile the Haskell into an ordinary library and write a .NET wrapper around it.
05:19 <ubsan_> the C++ should be done with `-O3 -std=c++14`
05:19 <ertes> hmm… i have LLVM 3.9
05:20 <ertes> but let me try anyway
05:20 cschneid_ joined
05:20 <ertes> You are using an unsupported version of LLVM! Currently only 3.7 is supported.
05:20 <ertes> nope, sorry
05:20 <tswett_to_go> I wonder how hard it would be to do a sort of middle ground.
05:20 <Cale> ertes: Well, it wouldn't bother me too much to have the interpreter interpret into IO actions.
05:20 <Cale> (or stuff involving them)
05:20 <tswett_to_go> Compile the Haskell into machine code but have it somehow use the .NET runtime system instead of the usual Haskell one.
05:21 <monochrom> middle ground is usually worst of both worlds...
05:21 <ertes> @remember monochrom middle ground is usually worst of both worlds...
05:21 <lambdabot> Okay.
05:21 <monochrom> hehe
05:21 <tswett_to_go> Well then, just go with the opposite middle ground. Compile it into .NET IL, but have it use the usual Haskell runtime system instead of the .NET one. :D
05:22 <ertes> tswett_to_go: at least that would allow .NET languages to have a type system
05:22 <monochrom> I think "somehow use the .NET runtime" is a lot of upfront investment.
05:22 carlosdagos joined
05:22 <mbw> It's the "draw the rest of the owl" part.
05:22 <monochrom> I mean after you finish, I'm sure I'll benefit too, but oh boy will it take you 6-12 months.
05:23 <ertes> i think luite is crazier than that… GHCJS is black magic
05:24 <monochrom> See what I mean by "1% of your program can contagiously dictate what language to use for the other 99%"? :)
05:24 <ertes> i thought that compiling GHC-haskell to JS was pretty much impossible for one person to do
05:24 <monochrom> Or at least "the FFI boundary is an annoyingly high overhead"
05:25 <Cale> ertes: Luite didn't know as well as you how hard it was
05:26 <ertes> in the sense that the bumblebee shouldn't physically be able to fly, but it doesn't know that, so it flies anyway?
05:26 <Cale> monochrom: At first I thought you were talking about runtime performance, but that interpretation makes a good deal more sense.
05:26 <ertes> (yes, i know that it's a misconception)
05:26 <monochrom> I was talking about runtime performance.
05:27 <monochrom> But I guess it generalizes too.
05:27 robkennedy joined
05:28 osa1 joined
05:29 forgottenone joined
05:29 <ubsan_> man, Rust does not have a good bitset library
05:29 <Cale> For the runtime performance case, usually what appears to happen is that after having recognised the problematic situation, people break the abstraction barrier for a bit and work on new primitives for the high level language with which they can solve the problem effectively. ByteString is my favourite example of that -- it made a lot of things which were possible but generally infeasible in Haskell easy.
05:30 <monochrom> Yeah that's true.
05:31 <ertes> ubsan_: you mean i get to complain about how ugly your rust code is, and that it doesn't look like rust at all? =P
05:31 takle joined
05:31 <ubsan_> ertes: lol, I'm just not gonna write it in rust
05:32 <ubsan_> rust seriously needs more generic programming
05:32 <Cale> Rust is the clear winner in this contest
05:32 <ertes> ubsan_: you should be able to translate the C version easily
05:32 mada joined
05:32 <Cale> For having avoided it altogether
05:32 <ubsan_> ertes: yeah, but laaazy
05:32 <monochrom> Haha, was going to ask you if you meant that. :)
05:32 <ertes> too bad… i would have liked to see how well rust does
05:33 <ubsan_> ugh, fiiiine
05:33 <ertes> wasn't that a fine piece of social engineering…
05:33 alx741 joined
05:33 Cell joined
05:34 orphean joined
05:35 lifter joined
05:35 DataComputist1 joined
05:36 sanett joined
05:37 BlueRavenGT joined
05:37 sdothum joined
05:39 patbecich joined
05:41 <mbw> Doesn't seem to be a productive language...
05:43 <ubsan_> mbw: well, this is not a strong area of Rust
05:43 <ubsan_> I basically have to use C
05:43 <tswett_to_go> I'm looking to see, if I wanted to modify GHC to compile to .NET IL, how far back in the process would I have to go...
05:43 <mbw> I'd just have said "it's still compiling" :)
05:44 <mbw> But then on the other hand, it won't be "idiomatic rust" I guess?
05:46 <tswett_to_go> Looks like the process is: text gets converted to a parse tree, that gets converted into Core, then STG, then C--.
05:47 <geekosaur> that's probably where you would do it. I'm given to understand the complex part is that .NET languages are expected to be able to activate each others' objects... which isn't even well defined in Haskell
05:48 <tswett_to_go> Which place is "that"?
05:48 <geekosaur> (there are a lot of .NET libraries you will not be able to interoperate with if you don't have objects that can communicate with other .NET objects. (COM?))
05:49 <geekosaur> usually after Cmm (which is not quite the same as C--)
05:49 <tswett_to_go> I mean, the fact that .NET languages can talk to each other's objects isn't much different from the fact that different .so libraries can call each other's functions and pass pointers between each other.
05:49 <ubsan_> ertes: https://gist.github.com/ubsan/a771eb2ffeb4f13c854304e2b061ef5b
05:50 patbecich joined
05:50 <ertes> ubsan_: that's C++… wrong link?
05:50 <geekosaur> it is, actually; cross-shared object calls are a simple low level interface, COM is a high level interface with complex underpinnings
05:50 spatial joined
05:50 <ubsan_> ertes: I put rust there too
05:51 danharaj joined
05:51 <tswett_to_go> I'm not talking about COM, though, or any kind of IPC.
05:51 sanett joined
05:51 <spatial> I thought I can read and write to an array and return in like this http://lpaste.net/353699
05:52 <ubsan_> ertes: within 10 ms
05:52 <ubsan_> (it's 10 ms faster, but I'll chalk that up to variance)
05:52 <spatial> Is that right ? I don't find the written values.
05:53 <mbw> What does println!("{}"...) do?
05:53 <ubsan_> mbw: it prints :)
05:53 <mbw> yeah, but what does the exclamation mark do, and "{}"?
05:54 peterbecich joined
05:54 <mbw> I didn't run it.
05:54 <kadoban> {} is a format specifier, like %d, except not
05:54 peterbec` joined
05:54 <kadoban> the ! means it's a macro
05:54 <kadoban> It's part of the name
05:54 lifter joined
05:54 <ubsan_> kadoban: no it isn't
05:54 <mbw> ah, so it's a convention?
05:54 <ubsan_> it's a part of the invocation
05:54 <cocreature> spatial: where are you writing to the array? I don’t see it in your code
05:55 <ubsan_> the name of the macro is "println", the invocation is "!(...)", "!{...}", or "![...]"
05:55 <tswett_to_go> Anyway, if you "truly" compile Haskell to .NET, you'll probably want to represent Haskell types with .NET types which are as close as possible.
05:55 <cocreature> spatial: also returning the same IOArray that you get passed in is not useful. it’s a mutubale structure so the reference the caller passed in will just be updated
05:55 <kadoban> *shrug* I don't know rust especially well
05:55 <mbw> get_unchecked_mut I guess
05:55 <ubsan_> mbw: huh?
05:55 <spatial> (nv,a) <- nextvalue player x a state should have written to it and returned.
05:55 <tswett_to_go> Represent "Maybe String" as... Haskell.Maybe<Haskell.List<Haskell.Char>>
05:56 <mbw> Was referring to cocreature's question.
05:56 <mbw> oh wait
05:56 takle joined
05:56 <ertes> thank you
05:56 <ubsan_> lol
05:56 <cocreature> spatial: how are you checking whether the values have been written?
05:57 <ertes> ubsan_: so it's 10 ms faster than C/C++?
05:57 <ubsan_> ertes: yeah, but I think that might be printf?
05:57 <ubsan_> I'm gonna test it again with rust using printf
05:57 <tswett_to_go> spatial: well, you're using one variable name to refer to two separate things. It would be less confusing if you wrote (nv,b) instead of (nv,a) and then used b instead of a on lines 11 through 14.
05:57 vlatkoB joined
05:57 <mbw> Or just disable sync_with_stdio
05:58 <ertes> ubsan_: printf shouldn't really make a measurable difference
05:58 <spatial> So assume this is alright. Will change reference names.
05:59 razi1 joined
05:59 <ahri> i have a "State" type for my game, and there are so many times when i come to write a bit of code to alter the state that i think "this only affects players, so i'll write it like: doSomething (State blah players) = State blah (somefunc players)" and that works for a while, until suddenly that somefunc turns out to need to alter the "blah" in there too. so i end up changing somefunc from "somefunc ::
05:59 <ahri> [Player] -> [Player]" to "somefunc :: State -> Player -> State", so that i can search through the players, alter the right one, and alter the "blah" too, returning State as a whole. is this a normal process that more experienced Haskellers go through or am i being a dumb newbie?
05:59 <ubsan_> ertes: looks like they're all within 50 msec
05:59 <spatial> cocreature: Trying to print it. But thought code has semantic \issues.
05:59 <ubsan_> depending on how I play with stuff
05:59 <ubsan_> as I keep running it
05:59 eacameron joined
06:00 <ubsan_> but I think C++ is the clear winner here
06:00 <cocreature> spatial: the main issue is imho that you are returning the array. that makes no sense unless you are creating a new array instead of just modifying the one that is passed as an argument
06:00 <ubsan_> because that code is actually nice to read lol
06:00 <geekosaur> ahri, at some point new Haskellers discover the State monad
06:00 <ertes> ahri: refactoring is of course normal, and you will need to do it in haskell as well
06:00 <Cale> ahri: In the large, the fact that the compiler helps you so much to make refactors when your expectations about the data model change is very helpful.
06:00 <spatial> cocreature: It is supposed to be mutable. It can't be ?
06:01 tromp joined
06:01 <tswett_to_go> spatial: an IOArray is mutable, but your code isn't attempting to mutate it.
06:01 <cocreature> spatial: it is mutable. what I’m saying is that returning the array after you mutated it is not useful since it’s still the same array that you got as an argument
06:01 <ertes> ahri: but it happens less often as you get better at haskell, and you will find ways to make your code more future-proof
06:02 <tswett_to_go> cocreature: I don't think it's the same array; the "a" which is returned isn't the same "a" as the argument.
06:02 <laudiacay> hey, does anyone have good resources about http things in haskell
06:02 <ahri> i get that refactoring is normal, but i'm sometimes torn between whether to just change to "somefunc :: [Player] -> ([Player], Blah)" out of laziness... but i think it's more readable to just deal with my State type
06:02 <spatial> tswett_to_go: I thought so too.
06:02 <laudiacay> also, TCP/IP operations (like making and sending packages to various IPs sorry i really don't know what im talking about but would like resources)
06:02 <cocreature> tswett_to_go: hm I guess it depends on the behavior of nextvalue. however, I would be surprised if it creates a new array. that kind of defeats the purpose of having a mutable array
06:03 <Cale> ahri: Also, if the common case is that most operations only act on players in some uniform way and don't touch the rest of the state, you might want to maintain that Player -> Player type for the functions which don't need anything more
06:03 <ertes> ahri: generally it pays off to combine data into smaller units
06:03 <Cale> ahri: Even if they ultimately get used by something of a more general type, this makes them individually easier to understand and test.
06:03 <ertes> ahri: i think that was misleading
06:03 <spatial> Let me debug some more as code semantics is ok.
06:03 <ertes> ahri: i meant it this way: smaller units are better than larger ones
06:05 lostman_ joined
06:05 <ahri> ertes: yeah, this is why outputing a tuple seems better in some ways; without access to the rest of the stuff in State i'm less likely to make a mistake in my code. but having this intermediate type (the tuple) that i then have to grab values out of via fst/snd is not particulrly nice to read
06:05 <Cale> ahri: Note that, for example, if it's common to just do something to all the Players
06:06 ludat joined
06:06 <ertes> ahri: you can just pattern-match
06:06 <ertes> ahri: let (y1, y2) = f x
06:06 <Cale> You can write a function (Player -> Player) -> ([Player], State) -> ([Player], State)
06:06 <Cale> (and really, you should define some data type for your complete game state -- it's important enough not to use pairs for that)
06:06 <mbw> that seems like something you could use mapAccum for.
06:07 <ertes> ahri: and yes, mapping functions are very useful
06:07 <Cale> Not even mapAccum
06:07 <ertes> ahri: (what Cale said)
06:07 <Cale> Just map -- it doesn't touch the State
06:07 <mbw> ah ok
06:08 <mbw> Then that function signature is confusing :)
06:09 sanett joined
06:09 <Cale> Well, if it was (p -> p) -> ([p], s) -> ([p], s) you wouldn't expect it to affect the s part ;)
06:09 <Cale> But yeah
06:09 <spatial> Can I print in terminalstatep :: ( IOArray Int Double) -> Int -> IO Bool ?
06:10 <ahri> Cale: perhaps i've confused the issue; in my case i'm not using the State monad; State is my own type representing my whole game state
06:10 <Cale> ahri: I understood this by the fact that you weren't applying State to anything :)
06:13 <ertes> ahri: you should probably pick a different name anyway
06:13 <ahri> i was actually unaware that i could use 'let' for pattern matching, i had only used it in ghci
06:13 <ahri> ertes: yeah, i'll swap to GameState to avoid confusion
06:13 <ertes> ahri: you can pattern-match almost everywhere
06:15 <mbw> I thought "AppState" was what the cool kids are using.
06:15 systemfault joined
06:15 <tswett_to_go> Can you have a statement like "(x,y) = (1,2)" at the top level?
06:15 <ertes> tswett_to_go: yes
06:16 <ertes> @let xs :: [Integer]; xs@[x1, x2, x3] = [2, 3, 5]
06:16 <lambdabot> Defined.
06:16 <ertes> > x2
06:16 <lambdabot> 3
06:16 <ertes> @undef
06:16 <lambdabot> Undefined.
06:17 windsing joined
06:17 takle joined
06:19 <spatial> What does this do ? do { ; putStrLn $ "Is it a terminal step ?" ; return result }
06:20 <spatial> Semicolon
06:20 <spatial> I mean. It prints.
06:21 <Cale> spatial: Empty statements are discarded.
06:21 <Cale> It does the same thing as if that semicolon weren't there
06:22 louispan joined
06:23 carlosdagos joined
06:24 mbw joined
06:25 CurryWurst joined
06:25 kshukla joined
06:26 kshukla joined
06:26 meba joined
06:27 hexagoxel joined
06:27 fizruk joined
06:30 <kshukla> I am trying to store input lines in a list then print the list: http://lpaste.net/353701 . "EOF" is the last line. I am not gettin any output. What am I doing wrong?
06:30 uglyfigurine joined
06:34 cschneid_ joined
06:35 <geekosaur> when you rerun main, it gets a new "list" initialized to []
06:36 <geekosaur> you need to rewrite this so you can pass the current list to the recursive function
06:36 <mbw> kshukla: This should give you name-shadowing warnings with ghc -Wall
06:38 <mbw> Although that's probably not the definitive hint here. Like geekosaur said, main is a function of type "main :: IO ()", i.e. it does not actually take any arguments. You would need a function of type fun :: [String] -> [String], for example.
06:38 <geekosaur> I should have said "makes" instead of "gets"
06:38 <geekosaur> it does not inherit the old one, but creates a new one
06:39 <mbw> Or rather [String] -> IO [String]...
06:39 <mbw> also geekosaur, what is that <<loop>> error I encounter when trying to run this interactively?
06:40 <mbw> I'm sure I've read about this before, on the ghc site.
06:40 BartAdv joined
06:40 <geekosaur> right, line 8 doesn't do what you think
06:41 <geekosaur> 1. bindings are not mutable. The "list" on the left side is a *new* binding unrelated to the old
06:41 <geekosaur> 2. the "list" on the right side of the = is the same one as on the left
06:41 <geekosaur> and trying to bind something to an expression starting with itself is left recursion and will generate <<loop>>
06:42 <mbw> ah, so it's a let x = x in x kinda thing?
06:42 <geekosaur> exactly
06:42 <mbw> The error output could be more conclusive lol
06:43 <mbw> Or maybe that is not easy to implement? Because of indecidability or something?
06:43 <mbw> *undeci...
06:43 <geekosaur> usually that's all it knows; the STG reducer puts a placeholder into the thunk being evaluated which does (error "<<loop>>"), which will be thrown if the expression is re-entered during reduction
06:43 <geekosaur> this happens at runtime; the compile time information to say anything more no longer exists
06:44 <Cale> If you compile with profiling, you might get more
06:45 <mbw> That might also be an opportunity to test the new DWARF debug data that ghc seems to be able to create now.
06:46 mk-fg joined
06:46 mk-fg joined
06:46 <mbw> No such luck with gdb/-g.
06:46 <mbw> I'm probably doing it wrong.
06:47 <geekosaur> I think it's still not fully impleented; I recall more complete support being an 8.2 thing
06:47 takle joined
06:48 <geekosaur> also, iirc there is an open stack bug report because it strips binaries and has no way to prevent it
06:48 moongazer joined
06:50 hexagoxel joined
06:50 <mbw> That's a problem. Also, compiling with -prof -auto-all and running via ./BinaryName +RTS -p doesn't change the output either.
06:50 <Cale> Try +RTS -xc
06:50 meandi_2 joined
06:51 patbecich joined
06:51 <kshukla> How to store input line by line in a list?
06:52 graygoose124_ joined
06:52 <mbw> Cale: This produces *** Exception blah bla stack trace \n Main.main.list,\n called from Main.main etc.
06:52 <mbw> Seems to be the way to go.
06:53 <mbw> kshukla: You can just use readFile, and then lines, which will split at the newline character.
06:53 <Cale> kshukla: There are a bunch of ways -- you can write something like do xs <- getContents; ... and then apply the lines function to xs to split it
06:54 <mbw> getContents reads from stdin.
06:54 <Cale> yeah
06:54 OnkelTem joined
06:54 <Cale> You could write a recursive function which takes the list of lines seen thus far (probably in reverse order) and accumulates them
06:54 <Cale> (and uses getLine)
06:55 halogenandtoast joined
07:02 _sras_ joined
07:03 bakayarou joined
07:03 <mbw> kshukla: Since you want to do the direct recursion approach, this would be something along the lines of this: http://lpaste.net/353702
07:03 <_sras_> How can I make the functions in a where binding available to all functions bodies?
07:04 <Cale> _sras_: Move them out of the where binding to the top level?
07:04 <mbw> _sras_: If I understood you correctly, either what Cale said, or replace pattern matching with a case expression.
07:04 <mbw> If you want the helper function to stay local
07:04 <mbw> .
07:05 <mbw> case expressions are uglier of course.
07:05 <Cale> Note that the things defined in the where clause will scope over multiple guards
07:05 <Cale> It's just that they have access to the variables bound on the left hand side of the equation, and so it doesn't make sense for them to scope over multiple parts of a function declaration
07:06 <_sras_> Cale: Yes. Right.
07:06 <_sras_> mbw: Case expressiosn cannot work if I have multiple arguments, right?
07:06 <mbw> Also, you can still treat a top-level function as a helper function. If you're inside a module, just don't export it.
07:07 caumeslasal joined
07:07 <kshukla> Sorry, I am new to haskell, but what does `IO [String]` in `fillList :: [String] -> IO [String]` mean. I have only seen `IO ()`.
07:07 <mbw> No problem. Read it like this:
07:07 <mbw> filList takes one argument, a list of strings.
07:08 JuanMiguel joined
07:08 sanett joined
07:08 vlatkoB_ joined
07:08 <mbw> The result of which is a generalized notion of a "computation", i.e. not a pure function, which 1. Returns a result value of type [String], and 2. produces some side-effects captured by "IO".
07:09 <mbw> _sras_: In case e of ... , 'e' can be any valid haskell expression. It's not like a switch statement in C, for instance, which can only test for integral values.
07:09 systadmin joined
07:09 <mbw> Or maybe I misunderstood your question.
07:10 <Rotaerk> kshukla, the () in IO () is a type too, just one for which there is only a single possible value. it's used when there's nothing meaningful to return
07:10 <_sras_> mbw: Yes. In case of multiple arguments, I can use a tuple..right?
07:10 <Cale> I would rather say that a value of type IO [String] is a description of some stuff which could be done, and at the end of doing that stuff, you would get a [String] as the result
07:10 <mbw> _sras_: Maybe it would be easiest if you pasted a concrete example.
07:11 <Cale> If it helps, the difference between IO [String] and [String] is like the difference between the program /bin/ls and a listing of files in your home directory
07:12 ziyourenxiang joined
07:13 <Cale> For example, getLine :: IO String is a value which describes how to get a line of text from the terminal (or stdin, if you prefer)
07:13 <mbw> That of course assumes that kshukla already knows about non-strict evaluation...
07:13 <Cale> Evaluating this description won't do much.
07:14 <Cale> It has to be executed, which is separate from evaluation, in order for anything to happen.
07:14 <Rotaerk> I usually read "IO x" as "an IO action that, when executed, produces an x"
07:14 <Cale> right
07:14 dawehner joined
07:15 <Cale> When a compiled program is run, the action you define called main will be executed, and in turn, it will usually be built up from smaller actions.
07:15 <Cale> If you type an IO action at the ghci prompt, ghci will notice that it's an IO action and execute it for you as well.
07:15 <Cale> (and it will also print the result, if it knows how)
07:16 <Rotaerk> kshukla, make sense or have you been thoroughly confused?
07:17 Einwq joined
07:17 <Cale> But yeah, it's important to realise that this execution (carrying out the effects described by IO actions) is separate from evaluation (a process of reducing expressions to values, typically so that patterns can be matched).
07:17 <kshukla> return type is IO [String], but you are returning a [String] ?
07:18 <Cale> kshukla: Well, your function is producing an IO [String] when applied
07:18 <Cale> But that result of type IO [String] is itself a program, which when executed, will result in a [String]
07:18 <Rotaerk> IO [String] is the "return type" of the function, but [String] is the "return type" of the IO [String] itself
07:18 <Cale> and that program can cause your computer to do anything that computers can do
07:19 <Cale> Whereas the function can do nothing more than to compute its result (which is that program)
07:19 <Rotaerk> i.e. evaluation of the function produces an IO [String], and execution of that action produces a [String]
07:19 <mbw> In list' <- fillList [], I "bind" the result to list'. I can do this only inside another IO action. If I would've written let list' = fillList [], list' would've been of type IO [String].
07:19 iomonad joined
07:20 <kshukla> @mbw in your program in your `if` you are returning `strings` which if of type [String]
07:20 <lambdabot> Maybe you meant: yow msg bf
07:20 <Cale> Yeah, inside a do-block, the statement v <- x means "execute the action x, and call its result v"
07:20 <Cale> If x :: IO t, then v :: t, and v will be usable throughout the rest of the do-block.
07:20 <Rotaerk> "but only when the whole do block is, itself, executed"
07:21 <Cale> Right, the do-block as a whole will itself be another one of these actions
07:21 <mbw> Yes, but its "return strings", not just strings.
07:21 owiecc joined
07:21 <Rotaerk> not necessarily
07:21 wei2912 joined
07:21 <mbw> Without the return, it would be a type mismatch.
07:22 <mbw> :t return
07:22 <lambdabot> Monad m => a -> m a
07:22 simendsjo joined
07:22 <Rotaerk> well I just mean, the last part of the do block doesn't have to be a return
07:22 <kshukla> OIC. So return is like an implicit type cast?
07:22 <mbw> i.e. take strings, and put them into IO. And like Rotaerk said, I don't have to do this in the else branch.
07:22 <Cale> return v is the action which does nothing except to, well, produce v as its result
07:22 <mbw> noo....
07:23 <Rotaerk> yea just because it's an IO "action" doesn't mean it necessarily *does* something, just that it might, depending on how it's defined
07:23 <Cale> return is a function of type a -> IO a here (actually its type is a bit more general than that, but for the sake of IO actions, that's its type)
07:24 carlosdagos joined
07:24 <Cale> Oh, should have mentioned: the result of the do-block is the result of the last action in it
07:24 <kshukla> ah... right
07:24 <Cale> So, when return v gets executed at the end of the do-block, the whole combined action returns v.
07:25 <Rotaerk> if you have: do { x <- getLine; return x; } you can simplify that to: do { getLine; } and further to just: getLine
07:25 <mbw> I could've written x <- fillList ...; return x. But then I would just "get x out of IO and put it right back in", so to say.
07:25 <Cale> Rotaerk: also you don't need semicolons at the end like that ;)
07:26 <Cale> (semicolon is a separator rather than a terminator)
07:26 <Rotaerk> oh :P I never use single line do blocks in actual code
07:26 eacameron joined
07:26 <_sras_> While makeing a type class how can I mark the minimal required function definitons to make a valid instance?
07:27 <mbw> {#- MINIMAL fun1 -#}.
07:27 <Cale> https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#minimal-pragma
07:27 <robkennedy> Is there a different function for `fix f x = if f x == x then x else fix f (f x)`?
07:27 <Cale> _sras_: ^^
07:27 <mbw> If I didn't screw up the braces.
07:27 <kshukla> @mbw why doesn't else require a return in your program?
07:27 <lambdabot> Maybe you meant: yow msg bf
07:27 <mbw> For the exact reason Rotaerk just gave, and me one line above.
07:28 <ezyang> robkennedy: Not int he stdlib, I'm pretty sure
07:28 <ezyang> :t iterate
07:28 <lambdabot> (a -> a) -> a -> [a]
07:29 <Cale> kshukla: The result of a do-block is the result of the last action in it -- return is just a function which happens to produce a boring action.
07:29 Cassiopaya joined
07:29 <Rotaerk> isn't fix usually defined as: fix f = let x = f x in x
07:29 <_sras_> mbw: Please take a look here http://lpaste.net/353703 . What I am trying to do is to move the bottom functions into the local scope of the instance definition.
07:29 <mbw> In fillList arg = something, something is of type IO [String]. Which is exactly the type of fillList arg2 in the else branch.
07:29 <Cale> Rotaerk: yes
07:29 <Cale> robkennedy's fix is a different function though
07:30 <robkennedy> Yeah I know that fix isn't the functions name
07:30 <Rotaerk> k
07:31 <kshukla> OK, so last expression in a do block should be of type IO (a) and return just makes that `a` an `IO a`?
07:31 <Cale> yeah
07:32 <Cale> return takes a value, and builds the action which does nothing except to have that value as its result
07:33 <Rotaerk> kshukla, if the thing you want to return in your do block is the result of the last action in your do block, you can just end it with that action; you really just need return if the result is *not* that of the last action
07:33 <Cale> right
07:33 <robkennedy> :t \f x -> let ys = iterate f x in fst $ filter (uncurry (==)) $ zip ys (tail ys)
07:33 <lambdabot> error:
07:33 <lambdabot> • Couldn't match expected type ‘(a, b0)’
07:33 <lambdabot> with actual type ‘[(a1, a1)]’
07:34 simukis__ joined
07:34 <robkennedy> `fst . head`. I see what you meant
07:34 Gurkenglas joined
07:34 <Rotaerk> kshukla, do { putStrLn "Type something..."; getLine } -- no return necessary... the result of the do block is whatever line is returned by getLine
07:35 <Rotaerk> but if I wanted to, say, get two lines and combine them or something, then I can do this: do { x <- getLine; y <- getLine; return (x ++ y) }
07:35 <robkennedy> How does ghc decide between what gets b's and what gets a3's?
07:35 <Cale> robkennedy: It tries to use the variables which occur in your explicit type signatures
07:35 <Cale> robkennedy: But if it has to invent variable names while typechecking, it's not very creative
07:36 fizruk joined
07:36 <Cale> It tends to just append numbers
07:36 <_sras_> kshukla: I don't know if this helps, but the 'return a' just calls the 'return' method in what ever monad instance you are in. So if you do 'return 5::Maybe Int' you get a 'Just 5'
07:36 <Cale> (we hadn't yet mentioned monads)
07:37 louispan joined
07:37 Fairy joined
07:37 robertkennedy joined
07:38 <Rotaerk> yea it's best not to graduate to the monad abstraction until *after* he's got some specific instances down...
07:38 bjz joined
07:38 coot joined
07:38 <Cale> Still, it might be worth explaining the do-notation in terms of (>>=)
07:38 <Cale> Some people like that :)
07:38 <Cale> There's an operation:
07:38 takle joined
07:39 <Cale> (>>=) :: IO a -> (a -> IO b) -> IO b
07:39 <mbw> _sras_: Kinda hard to do the refactoring when all the types are missing :(
07:39 gryle joined
07:39 <Cale> which, given some action x :: IO a and a function f :: a -> IO b gives you the action x >>= f :: IO b which when executed will first execute x, and then apply f to its result to figure out what to do next
07:40 <_sras_> mbw: all types are missing?
07:40 <Cale> i.e. if the result of executing x was v, then it will execute the action f v
07:40 <mbw> DepartureTime, DateWidget, ...
07:40 <Cale> and produce the result of that as its own
07:40 <Cale> do-notation is really syntactic sugar for using a bunch of (>>=)'s
07:41 <Cale> In particular, do { v <- x; <stmts> } = x >>= (\v -> do { <stmts> })
07:41 <ezyang> Man, newtype wrapping unwrapping is such a pain
07:41 <Cale> and do { x ; <stmts> } = x >>= \_ -> do { <stmts> } -- i.e. we discard the result of x
07:41 <ezyang> I wish generic programming worked for this sort of thing
07:42 <Cale> and do { let { <decls> } ; <stmts> } = let { <decls> } in do { <stmts> }
07:42 <Cale> and finally, as a base case, do { x } = x
07:43 jgt1 joined
07:44 <_sras_> mbw: is that better http://lpaste.net/353703 ?
07:45 <mbw> Ok, I'll take a look at it. Might take a moment though, since I have a splitting headache :(
07:45 <jgt1> 🤒
07:45 <Cale> kshukla: A monad is just a type M which, like IO, has operations of the right shape: return :: a -> M a, and (>>=) :: M a -> (a -> M b) -> M b (and these have to satisfy a few conditions) -- it turns up this pattern is common in functional programming, so we abstract over it to save ourselves from writing some common functions again and again.
07:46 takle joined
07:46 jgt joined
07:46 <mbw> _sras_: There's still a lot of stuff missing. I would feel uncomfortable giving advice without being able to get it to typecheck...
07:46 <mbw> Day, FormatTime, LocalTime.
07:47 lp joined
07:47 <mbw> Are monads still taught in terms of return?
07:47 <Cale> Yes?
07:48 <mbw> Because of Functor/Applicative/Monad I mean
07:48 <Cale> Rather than what?
07:48 <mbw> Just bind
07:48 <Cale> Oh, well, it's worth characterising them this way
07:48 <mbw> On the other hand, it makes sense of course. Otherwise you'd have to include Applicative.
07:48 <Cale> because you can go back and pick up Functor and Applicative for free
07:49 <Cale> fmap = liftM
07:49 <Cale> pure = return
07:49 <Cale> (<*>) = ap
07:49 <_sras_> mbw: Those are all from the `time` package...
07:49 <Cale> Or, well, perhaps I should have written out the definitions of liftM and ap in-place there :)
07:49 <mbw> _sras_: Ok.
07:49 <_sras_> mbw: https://hackage.haskell.org/package/time-
07:50 zcourts joined
07:50 <Cale> Applicative is kind of a fancier abstraction in my head -- it has a slightly lower power/weight ratio than Monad (at least in my opinion). Functor is worth introducing early though.
07:51 <_sras_> mbw: https://downloads.haskell.org/~ghc/7.0.3/docs/html/libraries/time-
07:51 nomotif joined
07:52 danvet joined
07:52 <mbw> _sras_: And you want ALL of those function to go into the instance declaration?
07:52 moongazer joined
07:53 <_sras_> mbw: not into, but would be nice if I can limit their scope to it.
07:53 <mbw> Cale: I actually found it easier to grok monads comming from applicative (and reading papers :/). Functor -> Monad is kind of a leap.
07:54 <Cale> Well, everyone is different
07:54 <Rotaerk> nah, some people are more equal than others
07:55 nomotif joined
07:55 <Cale> On the face of it though, I would expect that Applicative would be about as hard to pick up as Monad would be
07:55 <ubsan_> ertes: I tried to rewrite the C++ version to use compile-time evaluation
07:56 <Cale> Mainly because the sets of available examples of each are about the same
07:56 <ubsan_> turns out, clang doesn't like that big of arrays :P
07:56 <ubsan_> > constexpr evaluation hit maximum step limit; possible infinite loop?
07:56 <lambdabot> <hint>:1:44: error: parse error on input ‘;’
07:57 zcourts_ joined
08:00 jb55 joined
08:00 windsing_ joined
08:01 sdp joined
08:01 tromp joined
08:02 Silox| joined
08:02 doodlehaus joined
08:05 mel joined
08:05 ebzzry joined
08:06 s4kashya3 joined
08:07 ebzzry joined
08:07 takle joined
08:08 gryle left
08:10 raichoo joined
08:12 sanett joined
08:13 livingbeef joined
08:20 gawen joined
08:20 MarioBranco joined
08:20 arawack joined
08:21 t0by joined
08:22 <cocreature> does anybody know what stackage’s policy is for adding packages that depend on foreign libraries?
08:23 <ezyang> your best bet is probably to search in the issue tracker?
08:23 peterbec` joined
08:23 peterbecich joined
08:23 <cocreature> ezyang: I tried that but so far I did not find anything useful
08:24 <cocreature> I guess I’ll just try to add a package and see if they complain :)
08:24 <ezyang> "...forgiveness...blah blah blah..."
08:25 carlosdagos joined
08:25 <mbw> _sras_: K I've been shuffling things around etc. I think the most sensible way would be to let toDateWidget accept an additional argument, maybe something like data WidgetCfg = Full | NotSoFull, and let the typeclass just have one method. Then you'll just have one function that has to pattern match, which could be done via case expressions and one local function definition. Maybe I'm missing something, but I
08:25 <mbw> think other approaches would be too "clever". On the other hand I am probably missing a lot of context here :)
08:26 systadmin joined
08:26 <_sras_> mbw: Yes. That is what I figured as well...
08:27 meba joined
08:28 castlelore joined
08:29 <mbw> Then on the otherhand, this will be just isomorphic to toDateWidget' :)
08:30 <mbw> i.e. if I flip the arguments and have toDateWidget :: Cfg -> a -> DateWidget, then toDateWidget Full = toDateWidget' True, etc.
08:30 <mbw> I think you're just cleverly duplicating logic with these two methods.
08:32 <mbw> You can just let toDateWidget' accept a Cfg instead of a bool and inline it. Or you don't use Cfg, but bool. Then it's more or less already there.
08:32 castlelore joined
08:33 <mbw> I'd personally go with a dedicated type. Then match in a case expression and reuse the locally defined function
08:33 <mbw> You can of let one class method call the other, but I'd find that confusing.
08:33 takle joined
08:35 meff` joined
08:38 <mbw> Cale: About Applicative. I've found it very logical to consider it a necessary extention to Functor, i.e. fmap with binary/ternary/etc. functions. But on the other hand, I've never really _had_ to consider it a generalization of Monad, since I haven't been using Haskell for that long.
08:40 ragepandemic joined
08:41 mk-fg joined
08:41 mk-fg joined
08:41 ebzzry joined
08:42 JuanMiguel joined
08:43 <Cale> mbw: I suppose I usually think of liftA2 f x y as usually meaning something like do u <- x; v <- y; return (f u v)
08:44 hexagoxel joined
08:44 NeverDie joined
08:44 <Cale> Or x <*> y as meaning do f <- x; v <- y; return (f v)
08:44 <Cale> Of course, that breaks down when the thing isn't actually a monad
08:45 doomlord joined
08:48 <mbw> I like that aspect that from the container perspective, you have something like parallelism for fmap, concurrency for liftA2/3/..., and serial execution for bind. Even with the instance for ((->) r), it kinda shows how the "imperative style" trains you in thinking serially. Of course this doesn't hold for the general case, but I kind of found that insightful when first learning about it.
08:50 <mbw> The general case being non-commutative monads.
08:50 <mbw> Or some other subtlety.
08:51 jondot joined
08:51 <jondot> hello
08:52 <mbw> hi
08:52 <mbw> *sequencially
08:53 <jondot> im trying to understand where the terminology of FP comes from. for example, option/just/either/lift/map/zip and so on. i understand that much of this is from category theory but i'm trying to understand where did it first meet with programming practically?
08:53 <Cale> none of that comes from category theory
08:53 <jondot> was it haskell that first made the theory into programming practically?
08:53 <Cale> It comes from older functional programming which was mostly done in lisp
08:54 <Cale> Though Either is a Haskell thing. It was usually called Option in earlier MLs
08:54 <jondot> but lisp was not statically typed? i thought ML would be a root of these...
08:54 <Cale> Lisp had map, and I think zip as well
08:55 <jondot> yes, that's true. i'm still chasing to find the first paper / publication that mentions this
08:55 augur joined
08:56 <Cale> Actually, "lift" I would say is probably from mathematics, though we use it in Haskell in ways that are not *quite* the same as the relevant mathematicians use it, though in general I doubt they'd have any trouble with our usage.
08:56 <jondot> Cale: so my challenge is to find where was the first time that lift appeared and in which programming language
08:56 mettekou_ joined
08:57 <Cale> That's an easier question if you say which lift you mean
08:57 jgt joined
08:57 <jondot> the one that takes a function and lifts it to use Option, say.
08:57 <Cale> If it's the one for monad transformers, that would be Haskell, because monad transformers are an invention of Haskell programmers.
08:57 <Cale> mm
08:58 <Cale> Which language uses it that way?
08:58 <jondot> scala is one
08:58 <jgt> hey folks
08:58 <jondot> you can lift Math.abs to take option and return option
08:58 <Cale> Well, lift is a term used throughout mathematics in various ways, some technical, others not
08:58 <jondot> right
08:58 <jgt> is there a way to write this case without it being indented so far? http://sprunge.us/CZcj
08:58 <Cale> But usually with a sense of taking something specific and bringing it into a more general context.
08:58 kritzcreek_ joined
08:59 Mon_Ouie joined
08:59 <mbw> > fmap (abs) (Just (-3))
08:59 <lambdabot> Just 3
08:59 <mbw> like this?
09:00 <jondot> Cale: so I can ask this question from a different point of view. let's say you wanted to build and new functional programming language. how would you say 'yes this is the API i need'. would you survey a bunch of FP languages and copy the API?
09:00 systadmin joined
09:00 <Cale> Perhaps the canonical example coming from topology, where you have a fibration with a "base space" and a "total space", and then you might speak of "lifting" maps defined on the base space to the total space
09:01 <jondot> Cale: i'm guessing Clojure took a lot from Scheme/Lisp, but did they? or were there a bunch of publications that describe various APIs that they decided to follow?
09:01 <Cale> jondot: Depends on my reason for defining a new programming language
09:01 Kreest__ joined
09:01 sanett joined
09:02 <Cale> Also, most names are somewhat arbitrary -- it's probably more important to decide what concepts you want first, and then what names you'll give them.
09:02 takle joined
09:02 tromp joined
09:02 <jondot> Cale: well, how about introducing FP into a new language. So, Swift for example. Let's say you want to extend the standard library and make it FP happy.
09:02 <Rembane> Take the names from the domain.
09:02 <jondot> Cale: and where are these concepts rooted at?
09:03 <Cale> Well, the concepts are rooted in a particular way of thinking about and breaking down problems.
09:03 <jondot> BTW i can find plenty of papers covering Lisp, and covering the root concepts, without knowing Lisp or scheme or clojure. however I can't find any for ML type languages
09:04 <jondot> (that are based on category theory more profoundly than lispy languages because of types)
09:04 <Cale> I guess one place to start would be "Types and Programming Languages" by Benjamin Pierce
09:04 <jondot> aha1
09:04 <jondot> yeap that's one book on my buy list
09:04 Koterpillar joined
09:05 <kadoban> Is it accurate to say it's based on CT? My wording would be that it took a concept or two, mostly Monads, and that's about it
09:05 <Cale> If you want a mathematically abstract version of typed functional programming, you might look to type theories such as System F and Martin-Löf type theory
09:05 <Cale> and the calculus of constructions
09:06 <Cale> kadoban: Yeah, well, products and sums before that
09:06 Koterpillar joined
09:06 <Cale> But it's hard to *really* say that's the influence of category theory
09:06 <Koterpillar> How do I pronounce SYB?
09:06 <Cale> "Scrap Your Boilerplate"
09:06 <kadoban> Hmm
09:06 <Cale> Or "ess wye bee"
09:07 mstruebing joined
09:07 ner0x652 joined
09:07 <Koterpillar> thanks
09:07 <Cale> There's certainly a fundamental sort of connection between logic, category theory, and type theory
09:08 <Cale> (and then functional programming as an application of type theory)
09:08 <jondot> and i'm looking for the series of publications that flushes that connection out :)
09:08 <Cale> and it's hard to pick apart which of these three was responsible for originating any particular idea
09:09 <jondot> i get a stronger feeling i need to look around publications dealing with ML
09:09 <Cale> because as soon as you can say something in one of them, you can probably say it in the others
09:09 <Cale> So, the connection I'm referring to is called the Curry-Howard correspondence
09:10 <Cale> In logic, if you know that A implies B, and you know that A, then you can conclude B
09:10 <Cale> In lambda calculus, if you have f: A -> B, and you have x: A, then you can form f x: B
09:11 mmn80 joined
09:11 <Cale> In logic, if you want to prove A implies B, then you start by assuming A, and attempt to conclude B, and if you're successful, by natural induction, conclude A implies B
09:12 sanett joined
09:12 <Cale> If lambda calculus, if you want to construct a term of type A -> B, then you start by introducing a variable (x:A), and attempt to construct a term y:B, and if you're successful, then you may form the lambda term (\x -> y) : A -> B
09:13 <Cale> Similar characterisations can be given for the connectives, with "and" corresponding to the pair type (its introduction rule corresponding to the data constructor for pairs, and elimination rules the projections to the components)
09:14 <Cale> and "or" corresponding to Either, with its introduction rules corresponding to the Left and Right constructors, and its elimination rule corresponding to well, the function we call 'either' in Haskell.
09:14 <Cale> :t either
09:14 <lambdabot> (a -> c) -> (b -> c) -> Either a b -> c
09:14 ragepandemic joined
09:15 <Cale> (If we can conclude c from a, and we can conclude c from b, then we may conclude c from a \/ b)
09:16 <jondot> Cale: interesting
09:16 <Cale> and these things correspond to various concepts in category theory as well: implications and function types correspond additionally to exponential objects
09:16 SpinTensor joined
09:16 <Cale> "and" and product types to product objects
09:17 <Cale> "or" and sum types to coproducts
09:17 chaosmasttter joined
09:17 <Cale> (which are also called sums in category theory)
09:18 nepiktaz joined
09:18 <jondot> so both lambda calculus and category are accessible, yet how did they make it into a programming language, and which one was the first?
09:18 <jondot> was it miranda?
09:19 <Cale> Well, lambda calculus, even before electronic computers when it was a sort of notation for logical proofs, always had a notion of "reduction" or "simplification" of proofs, which we'd now think of as "evaluation"
09:20 <Cale> as for how it came into programming, well, untyped lambda calculus was an inspiration to introducing lambda to lisp.
09:20 <Cale> I don't know if there's anything earlier than that.
09:20 sanett_ joined
09:21 <Cale> and then the typed side of things came first with ML, so far as I'm aware
09:22 Kreest_ joined
09:22 bondan joined
09:22 <louispan> Hi all, I've been creating yet another GUI framework which is now in a stable state. Please have a look and let me know what you think:
09:22 <louispan> https://www.reddit.com/r/haskell/comments/6099gw/yet_another_gui_framework_glazier_glazierreact/
09:23 <Cale> There was, it seems, a bit of a renaissance of type theory and lambda calculus which went on in the 1970's though, in parallel between logicians and computer scientists
09:23 Kreest_ joined
09:23 <Cale> https://en.wikipedia.org/wiki/System_F
09:23 <Cale> "System F was discovered independently by logician Jean-Yves Girard (1972) and computer scientist John C. Reynolds (1974)."
09:24 <jondot> Cale: i'm tracing it now to SASL
09:24 <Cale> I don't know how I quite feel about that characterisation of what occurred, but something close enough :)
09:24 Kreest_ joined
09:24 <Cale> and at nearly the same time...
09:24 <louispan> The todo mvc example can be played with here: https://louispan.github.io/glazier-react-examples/ Only 170kb of gzipped javascript (including React)
09:25 Kreest_ joined
09:25 sanett joined
09:25 <Cale> https://en.wikipedia.org/wiki/Intuitionistic_type_theory
09:25 carlosdagos joined
09:25 <jondot> you get some of the terms here, in 'prelude' https://web.archive.org/web/20150402133901/http://www.eis.mdx.ac.uk/staffpages/dat/saslman.pdf
09:25 <jondot> it's amazing how 'prelude' meant nothing to me until now
09:26 Kreest_ joined
09:26 <Cale> which traces its roots back to much earlier intuitionistic logic of Brouwer and Heyting and Kolmogorov that goes back to the 1920s
09:27 <Cale> Oh, yeah, Turner would be another guy I shouldn't neglect to mention :)
09:28 <Cale> and Landin, with his "The Next 700 Programming Languages"
09:28 <Cale> http://www.cs.cmu.edu/~crary/819-f09/Landin66.pdf
09:29 <Cale> and his language ISWIM, which was never implemented on a computer, but influence the design of a lot of functional programming languages
09:29 <Cale> d*
09:31 MarcelineVQ joined
09:31 catsup joined
09:31 <Cale> That was in 1966, and he has where clauses and an equational sort of notation which got put into SASL and ML
09:31 <Cale> (and Haskell, of course)
09:32 <Cale> Turner was also responsible for Miranda, of which Haskell started out as sort of an open source clone :)
09:32 <kadoban> I've never heard that last part of that sentence before, that's a bit amusing.
09:32 catsup joined
09:34 <Cale> Well, I'm being a little glib about it, but that's not an entirely unfair characterisation :)
09:34 free_beard joined
09:35 mk-fg joined
09:35 mk-fg joined
09:35 <jophish> ertes: It certainly worked well enough for me to get an example program running when vulkan was first out
09:36 <Cale> I guess the programming language theory researchers got a little tired of putting "Miranda is a trademark of Research Software Ltd." in all their papers
09:36 <kadoban> Hah
09:36 systadmin joined
09:36 <jophish> however the spec has moved on since then and I'd guess that it no longer parses
09:36 Iskungen joined
09:36 <jophish> (probably just a handful of minor issues though)
09:37 <Cale> https://www.cs.kent.ac.uk/people/staff/dat/miranda/Overview.html -- if you have a look at the syntax, it would take a moment to realise that it's not Haskell -- the type signatures would give it away, and data declarations
09:38 sanett joined
09:38 <kadoban> Wow, I didn't know they looked so very similar
09:39 nilof joined
09:39 livingbeef joined
09:40 thc202 joined
09:40 ngc24 joined
09:41 <jgt> hey folks, how can I go from a `Maybe Text` to a `Maybe Int`? I was thinking to `fmap readMaybe`, but this results in a `Maybe (Maybe Int)`. Do I need a monad here to unwrap the inner Maybe?
09:41 windsing joined
09:42 <mbw> jgt: I don't think that this return type is unreasonable, since reading can fail. You should be able to just pattern match. Especially if you're already inside the "Just case" of Maybe Text.
09:42 <mbw> In which case it would be just Maybe Int.
09:43 sanett joined
09:43 louispan joined
09:43 <kadoban> jgt: You can indeed use maybe, either by using "join" on that result, or by using >>= in the first place instead of fmap + join
09:43 <jgt> yeah, I understood the part where reading could fail
09:43 <jgt> I could do it the case way, but it might be a bit ugly
09:43 <kadoban> s/indeed use maybe/indeed use Monad/
09:44 ngc24 joined
09:44 <jgt> kadoban: how would that look? I can't quite see it in my head
09:45 <kadoban> :t (>>=)
09:45 <lambdabot> Monad m => m a -> (a -> m b) -> m b
09:45 <kadoban> So, theValue >>= readMaybe looks like the right puzzle connection
09:46 <kadoban> Where theValue :: Maybe Text
09:46 <jgt> oh!
09:46 vlatkoB joined
09:46 <jgt> yeah, that totally works
09:46 <ngc24> Hello need some help ~ How do I read an arbitrary number of lines till some delim from stdin and store it in a list? To use forM I need to know the number of lines.
09:46 <jgt> thank you :)
09:46 <kadoban> Anytime
09:47 <Cale> ngc24: You might just write a recursive loop
09:48 <Cale> ngc24: loop xs = do x <- getLine; if isMyDelimiter x then return (reverse xs) else loop (x:xs)
09:49 <ngc24> Cale: Thanks!!
09:49 MoALTz joined
09:49 <jgt> > Just "123" >>= readMaybe
09:49 <lambdabot> error:
09:49 <lambdabot> Variable not in scope: readMaybe :: [Char] -> Maybe b
09:50 <jgt> > Just "123" >>= Text.Read.readMaybe
09:50 <lambdabot> error:
09:50 <lambdabot> Not in scope: ‘Text.Read.readMaybe’
09:50 <lambdabot> No module named ‘Text.Read’ is imported.
09:50 <jgt> :(
09:50 <kadoban> Ya, lambdabot doesn't have everything, and I always have a hard time guessing what name it'd be under for some stuff it does
09:51 <jgt> well when I run it locally with Text.Read imported, `Just "123" >>= readMaybe` evaluates to `Nothing`
09:51 <jgt> and I'm not sure why
09:51 <geekosaur> ExtendedDefaultRules
09:51 <geekosaur> you didn't give it a type, so it defaulted the type to ()
09:52 <Iskungen> is porting code to haskell a good obfuscation method?
09:52 <kadoban> Only if your target "audience" doesn't know haskell I suppose
09:52 <Cale> Iskungen: Except when it's a good clarification method
09:52 burdges joined
09:53 <Cale> Iskungen: I've actually translated obfuscated C code to Haskell in a fairly mechanical way so that I'd be able to reason about its behaviour a bit more clearly and figure out what it was doing.
09:53 <jgt> geekosaur: Ah! Right you are. Thank you!
09:53 <jgt> I wish the compiler errors were a little more hand-holdy like Elm
09:55 Yuras joined
09:55 <jgt> god damn my code ends up being beautiful with monads
09:56 <jgt> I have a lot of deeply nested case statements, where I'm usually breaking apart Eithers in my code
09:56 <jgt> so good to see that kind of thing fall away
09:56 <Cale> Just starting out having one function per point of control, with function parameters for each of the variables in scope, and then having the functions apply each other to new arguments according to the control flow and updates to variables
09:56 <kadoban> jgt: Yeah, they're *really* nice for that
09:56 <Cale> and that gives you a mess of equations, and you can start simplifying like highschool algebra
09:57 <Cale> until you hopefully end up with something that is actually comprehensible
09:58 RegEchse joined
09:58 systadmin joined
09:58 <jgt> how my little bit of code looks now: http://sprunge.us/giSa
09:59 <jgt> is that idiomatic? Or would a Real Haskeller™ do it different?
09:59 owiecc joined
09:59 <Cale> I would use =<< but that's personal preference
09:59 systadmin joined
10:00 govg joined
10:00 <jgt> Cale: how? I haven't used that operator before
10:01 <Cale> x >>= f is the same thing as f =<< x
10:01 <jgt> ah
10:01 <jgt> oh, it didn't type check because again I didn't specify the types
10:02 fizbin joined
10:02 <Cale> didn't you?
10:03 albertus1 joined
10:03 <jgt> Cale: this is what I got back: http://sprunge.us/eeiG
10:04 zero_byte joined
10:04 <jgt> maybe I'm using a different listToMaybe
10:05 <Cale> Ah, I see
10:05 <Cale> You just need something in there to do some reading like on the other side
10:06 <Cale> listToMaybe wants a list of things
10:06 sanett_ joined
10:06 mk-fg joined
10:06 mk-fg joined
10:07 <jgt> oh, I have to unpack that Text first into a String
10:07 <jgt> because I want a list of Chars
10:08 uglyfigurine joined
10:08 sanett joined
10:08 <Cale> ah
10:08 <Cale> I missed that type Category = Char
10:10 <jgt> how do I unload Prelude from ghci?
10:13 zv joined
10:13 <int-e> jgt: does import Prelude () (or perhaps import qualifed Prelude) achieve what you need?
10:14 <int-e> jgt: if you want to remove prelude completely (because of class instances or perhaps rebindable syntax) I think you need to start ghci with -XNoImplicitPrelude
10:15 <int-e> jgt: oh this seems to work as well: :set -XNoImplicitPrelude, then :reload
10:17 <jgt> thanks!
10:17 dawehner joined
10:17 <jgt> and now I realised that it was getting Prelude from some other module which explicitly imports it
10:18 louispan joined
10:18 eacameron joined
10:19 mkoenig joined
10:22 louispan joined
10:22 Yuras joined
10:23 <jgt> wonderful; this all works http://sprunge.us/ZJSR
10:23 <jgt> except I can't toJSON a ByteString, but that's expected, and is the next thing to do
10:24 peterbecich joined
10:24 peterbec` joined
10:25 Glooomy joined
10:26 carlosdagos joined
10:27 bjz_ joined
10:27 henrik2 joined
10:28 meba joined
10:35 netheranthem joined
10:35 halogenandtoast joined
10:36 lp joined
10:37 louispan joined
10:38 n123 joined
10:39 zdenal joined
10:40 <n123> hello all - I have this annoying issue trying to install hsffig: $ cabal install hsffig => http://sprunge.us/RiKE ???
10:40 <n123> any clue anybody what the problem could be ?
10:44 <cocreature> n123: hsffig depends on an ancient version of parsec that does not support GHC 8.0
10:45 <n123> ... so there is currently no FFI in haskell ??
10:45 oish joined
10:45 <n123> or is there another tool that I am not aware of ?
10:46 <cocreature> you don’t need any tool for doing ffi. C ffi is part of the haskell standard
10:46 <cocreature> I’m not sure if there is an up2date tool for autogenerating bindings based on headers
10:47 <n123> there is no mention of the tool being deprecated at https://wiki.haskell.org/FFI_imports_packaging_utility
10:47 <cocreature> there are various tool that simplify writing ffi bindings by reading the headers such as c2hs
10:47 <n123> aha
10:47 <jgt> what technique should I use to get rid of this deep nesting? http://sprunge.us/hgXf
10:47 <cocreature> n123: well it’s a wiki. if nobody feels like updating it, it’s not going to be updated :)
10:48 <jgt> I'm thinking perhaps EitherT? Or someone else maybe hinted at “kleisli arrows”, but I have no idea what that is
10:48 <n123> "This page was last modified on 13 September 2013, at 23:51" --- aha
10:48 <n123> all right thanks
10:50 <jgt> I've read https://ocharles.org.uk/blog/posts/2012-07-24-in-praise-of-EitherT.html but I didn't *quite* get it
10:51 <cocreature> n123: iirc https://wiki.haskell.org/Foreign_Function_Interface is fairly good at explaining how FFI works
10:52 <cocreature> jgt: do you know how you would remove that nesting if there was no IO involved?
10:53 Jackneill joined
10:54 <jgt> cocreature: I don't *know*, but I *think* I chain all the Eithers together with a bunch of >>=s
10:54 <cocreature> jgt: right or using do notation
10:54 lukaramu joined
10:54 <jgt> cocreature: sure
10:55 <jgt> cocreature: but am I right in thinking (and extrapolating from your question), that it doesn't quite work the same inside an IO?
10:55 <cocreature> jgt: so you can use >>= for Either and you can use >>= to sequence several actions. the problem you are experiencing here is that you have "IO (Either a b)" to somehow combine the effects of >>= on IO and >>= on Either
10:55 <cocreature> jgt: ExceptT (which for some reason is what we call EitherT these days) is exactly that
10:56 <Cale> http://www.cse.unsw.edu.au/~chak/haskell/ffi/ffi/ffi.html -- the FFI portion of the Report is also quite readable (even compared to the rest of the Report)
10:56 <cocreature> ExceptT IO (Either a) b is just a wrapper around IO (Either a b)
10:57 sepp2k joined
10:58 <jgt> cocreature: https://www.schoolofhaskell.com/user/commercial/content/exceptions-best-practices#exceptt-io-anti-pattern
10:58 <jgt> > It is almost always wrong to wrap an ExceptT, EitherT, or ErrorT around an IO-based transformer stack.
10:58 <lambdabot> <hint>:1:45: error: parse error on input ‘,’
10:58 <jgt> is that relevant here?
10:58 raycoll joined
10:58 <jgt> sorry lambdabot; confused markdown blockquote and lambdabot expression
10:58 <cocreature> jgt: not really. the point of that article is that it might make sense to replace Either with exceptions. but if you are already using something of the form IO (Either a b) then using ExceptT is fine
10:59 numeo joined
10:59 bennofs joined
11:01 cschneid_ joined
11:02 <jgt> cocreature: what would my exception type be?
11:02 Snircle joined
11:02 grayjoc joined
11:04 <cocreature> jgt: that’s up to you to decide. something that expresses the failure conditions appropriately. I don’t know when zrevrange fails
11:05 <jgt> cocreature: can I give it something meaningless until I know better?
11:05 ziocroc joined
11:06 <cocreature> jgt: sure, you just need something that is an instance of Exception
11:07 mkoenig_ joined
11:09 justicefries joined
11:11 vydd joined
11:11 vydd joined
11:11 <jgt> ugh. This is complicated. I'll come back to it after I've read up a bit more on monad transformers
11:12 Xanather joined
11:12 jeltsch joined
11:12 wildlander joined
11:13 <cocreature> jgt: if you can provide a small code sample that compiles, I can transform it to ExceptT for you if you think that’s helpful. it’s just a bit hard to do this without being able to compile it since I’ll definitely screw up the types :)
11:14 <jgt> cocreature: I'm not sure I can; it's part of a Yesod app, so it's not quite so self contained
11:14 <jgt> I'll give you this module though
11:14 <jgt> cocreature: this almost works: http://sprunge.us/SRSU
11:15 <jgt> what doesn't work is doing toJSON on a ByteString, but that's expected
11:15 puregreen joined
11:15 OnkelTem joined
11:16 lp joined
11:16 patc joined
11:16 <cocreature> alright, give me a few minutes
11:17 <jgt> but actually changing that line to `return $ toJSON $ show companies` makes it compile, even if the result is nonsense
11:19 <ggVGc> are you saying if it compiles it's not actually correct anyway?
11:19 <ggVGc> heresy
11:20 <jgt> 😅
11:20 louispan joined
11:21 oish joined
11:21 <jgt> ok, it's not totally nonsense, it's just overly wrapped/escaped
11:21 <jgt> which I'll take over ‘undefined is not a function’ any day
11:21 psychicist__ joined
11:23 t7 joined
11:24 biglama joined
11:24 <patc> Need help - How do I display every n-th element of a list, say I need to display every 4-th eleemnt?
11:24 cfricke joined
11:26 louispan joined
11:27 <cocreature> jgt: http://lpaste.net/353710
11:27 carlosdagos joined
11:27 Xanather joined
11:28 <cocreature> jgt: the fact that hedis requires that you work in RedisCtx instead of plain IO slightly complicates things since you need to define the necessary instances for RedisCtx and MonadRedis
11:29 ludat joined
11:29 patc joined
11:31 <jgt> cocreature: oh wow, that's much more concise!
11:31 <jgt> thank you so much!
11:31 <cocreature> np
11:34 livingbeef joined
11:35 systadmin joined
11:36 uglyfigurine joined
11:38 cloudhead joined
11:42 patc3 joined
11:42 windsing joined
11:44 sanett joined
11:44 eacameron joined
11:44 petervaro joined
11:45 moongazer joined
11:45 silver joined
11:46 forgottenone joined
11:47 sanett joined
11:47 magneticduck joined
11:48 dawehner_ joined
11:52 Zialus joined
11:53 sanett_ joined
11:54 hackebeilchen joined
11:56 JagaJaga joined
11:59 osa1 joined
12:01 <halogenandtoast> Any suggestions for starting a yesod app with an elm frontend? Is elm-yesod the way to go... it seems outdated.
12:03 shesek joined
12:03 nschoe joined
12:04 cpup joined
12:04 peterbecich joined
12:04 peterbec` joined
12:05 sword865 joined
12:05 JagaJaga_ joined
12:08 Fairy joined
12:11 bjz joined
12:16 systadmin joined
12:18 systadmin joined
12:19 sanett joined
12:21 sphinxo joined
12:22 beanbagu1 joined
12:24 curious_corn joined
12:24 systadmin joined
12:27 systadmin joined
12:28 carlosdagos joined
12:30 initiumdoeslinux joined
12:32 wtetzner joined
12:32 meoblast001 joined
12:32 oish joined
12:32 sanett joined
12:36 YongJoon joined
12:37 ebzzry joined
12:37 lep-delete joined
12:38 robotroll joined
12:39 cbaatz joined
12:39 halogenandtoast joined
12:39 YongJoon joined
12:41 phils_ joined
12:41 JuanMiguel joined
12:42 YongJoon joined
12:42 castlelore joined
12:45 stoopkid joined
12:48 <phils_> what is the best book for learning haskell
12:49 sdothum joined
12:50 <hpc> @where learnhaskell
12:50 <lambdabot> https://github.com/bitemyapp/learnhaskell
12:51 <hpc> ^ this is a meta-resource that might help
12:51 <hpc> there's two major resources that it does not mention iirc
12:51 <hpc> @where lyah
12:51 <lambdabot> http://www.learnyouahaskell.com/
12:51 <hpc> @where rwh
12:51 <lambdabot> http://www.realworldhaskell.org/blog/ http://book.realworldhaskell.org/read/
12:52 <hpc> i learned from lyah, but it does have a few issues like lack of exercises
12:52 matchwood joined
12:52 <hpc> RWH has a thorough second half, but you most likely will want to use CIS194 for learning the language itself
12:53 <sphinxo> say I'm making a library for some extra string utils, how should I namespace it? Data.String.<something> ?
12:53 fizruk joined
12:54 <matchwood> Hi all, looking for a little guidance on how packages are versioned and distributed - I'm a little confused particularly by this: https://hackage.haskell.org/package/mtl-2.2.1
12:54 <matchwood> The hackage package version is 2.2.1
12:54 <matchwood> With dependencies transformers (>=0.4 && <0.6)
12:54 <Theophane> sphinxo: if it works on the [Char] type, yeah better prefix it with Data.String.YourLib =)
12:55 <matchwood> but if you look at the .cabal in the source package https://hackage.haskell.org/package/mtl-2.2.1/src/mtl.cabal it specifies build-depends: base < 6, transformers == 0.4.*
12:55 <matchwood> Similarly, in the git repo https://github.com/ekmett/mtl the change in transformers dependencies also goes along with a bump in version to 2.2.2
12:56 <matchwood> So something weird is going on.
12:56 wildlander joined
12:57 <matchwood> (the context for this is I'm trying to hack together a version of ghcjs that works for stack lts-8.0, so I need repo refs for a version of mtl that matches that one on hackage - i.e. version 2.2.1 but with expanded transformers depedency)
12:57 <matchwood> Anyone know where hackage / stackage is getting that from?
12:57 wildlander joined
12:58 buttbutter joined
12:58 <cocreature> matchwood: you can make revisions to a cabal file directly without uploading a new version. you are pointing at the original cabal file, the updated one is https://hackage.haskell.org/package/mtl-2.2.1/mtl.cabal
12:59 Yuras joined
12:59 <matchwood> cocreature: when you say that, do you mean that the package authors on hackage can do that?
12:59 <cocreature> matchwood: yep
13:00 <matchwood> ok, so there is no necessary relationship between the git source of a package and the contents of the package on hackage or elsewhere?
13:01 <cocreature> matchwood: you don’t even need revisions to cabal files for there to be no relation. if you upload a package you upload a tarball including among other things a cabal file and the source url contained in that is used as the git source shown on hackage. but nothing enforces that this is even an url that exists
13:01 mmhat joined
13:01 <cocreature> it’s just useful metadata
13:01 <maerwald> matchwood: it's bad practice of maintainers, that's all
13:03 <matchwood> ok thanks, that all makes sense (even if confusing) - I knew that the source url was not necessarily related but I assumed that if there was an active github repo for it then it would reflect the state of the package on hackage...
13:04 <matchwood> Can any file be revised for hackage or is it just the cabal file?
13:04 <cocreature> only cabal files
13:05 <cocreature> the main motivation is that you can bump upper bounds if your package builds against a newer version without any changes
13:05 uglyfigurine joined
13:05 <matchwood> cocreature: ok I hoped it was that, otherwise things could get very messy!
13:05 peterbecich joined
13:05 peterbec` joined
13:06 pavonia joined
13:06 <cocreature> yeah
13:06 <cocreature> tbh it’s already slightly messy but it’s also quite convenient to be able to bump bounds without having to do a new release each time
13:06 Lord_of_Life joined
13:07 hexagoxel joined
13:08 <matchwood> Yeah, except in the cases that other code relies on the git source directly! In any case ghcjs-boot is setup to patch packages, so I can simply add a patch that bumps the upper bounds
13:08 oisdk joined
13:09 <matchwood> not really an issue, just wanted to be sure that I understood what was going on with hackage etc so I could be sure it would be using the same underlying code in the package
13:09 grayjoc joined
13:10 <halogenandtoast> hmm channel seems active now, so maybe I'll try asking again. Does anyone have any suggestions for writing a yesod/elm app (or snap/elm, or whatever).
13:10 twanvl joined
13:10 <matchwood> though tying hackage /stackage packages transparently to vc commits would be nice!
13:12 <matchwood> halogenandtoast: I'm not sure what you mean by suggestions? As in, resources for learning how to do it?
13:15 Vzox01 joined
13:17 cschneid_ joined
13:19 <halogenandtoast> matchwood: more like, is there a good way to integrate them for example there is elm-yesod but it looks like it hasn't been updated in a long time
13:20 Hoier joined
13:22 MarioBranco joined
13:24 spacedog82 joined
13:26 <matchwood> halogenandtoast: ah a common story. I can't help with that sadly, but I will say that the current energy of front-end haskell integration seems to be in ghcjs and stuff like reflex-frp rather than in haskell-like languages
13:28 eSVG joined
13:28 carlosdagos joined
13:31 ragepandemic joined
13:31 moth joined
13:32 <jgt> is there a way I can map a bunch of substitutions over some bytestring? So like `f "foo baz" [("foo", "bar"), ("baz", "qux")] ==> "bar qux"`?
13:32 uglyfigurine joined
13:33 owiecc joined
13:35 lukaramu_ joined
13:36 rekahsoft joined
13:37 <jgt> looks like I can compose together a whole bunch of Data.List.Utils.replace functions
13:37 beanbagula joined
13:37 tromp joined
13:44 windsing joined
13:45 AndreasK joined
13:47 jomg joined
13:47 mda1 joined
13:49 plutoniix joined
13:49 systemfault joined
13:49 sanett joined
13:51 systemfault joined
13:52 systemfault joined
13:52 <halogenandtoast> matchwood: as thanks, I'm wondering if I should just build two different apps then, the elm front-end and the haskell-backend/api
13:53 <halogenandtoast> Deployment becomes a pain though
13:53 marcopullo joined
13:53 systemfault joined
13:54 <matchwood> halogenandtoast: Is there any particular reason you wouldn't want to go down the ghcjs route?
13:54 <matchwood> halogenandtoast: also you might be interested in this https://github.com/mattjbray/servant-elm#readme
13:54 <matchwood> servant is an awesome type safe routing / serving library
13:55 <halogenandtoast> I like and want to use Elm. I want to use the reactive functional programming setup.
13:55 <matchwood> http://haskell-servant.readthedocs.io/en/stable/
13:55 doodlehaus joined
13:56 moongazer joined
13:57 oisdk joined
13:58 <matchwood> halogenandtoast: fair enough! Definitely worth looking into servant though - that integration with elm is pretty new so should hopefully be suitable
13:58 connrs joined
13:59 <halogenandtoast> I'll try and look in to it
13:59 besenwesen joined
14:04 <stevenxl> I folks. I am doing an exercise where I have to redefining map f in terms of foldr.
14:04 sanett joined
14:05 <stevenxl> This is my thought process and my result.
14:05 <stevenxl> Can someone help me figure out if there are any glaring holes in my understanding of this:
14:05 <stevenxl> https://gist.github.com/StevenXL/1592c92f6a32b97ff9c0e381237ca005
14:06 peterbecich joined
14:06 peterbec` joined
14:06 <stevenxl> Also, it is possible for me to check my answer in GHCi?
14:06 <lyxia> that's good
14:07 uglyfigurine joined
14:07 <lyxia> > map (>= 0) [1, -1, -1, -1, 1 :: Int]
14:07 <lambdabot> [True,False,False,False,True]
14:07 <stevenxl> lyxia: thank you!
14:08 <lyxia> > (\f xs -> foldr (\h t -> f h : t) [] xs) (>= 0) [1, -1, -1, -1, 1 :: Int]
14:08 <lambdabot> [True,False,False,False,True]
14:08 <lyxia> stevenxl: does checking like that work for you ^
14:10 <stevenxl> Yes, I see what you mean. Thank you. Would typing map f = foldr (\x rst -> f x ++ rst) [] into ghci and not getting an error back be enough? Would ghci throw an error if that answer was wrong?
14:10 Ayey_ joined
14:11 <stevenxl> I see what you mean though. Run both the map version and the foldr definition and ensure the results are the same.
14:11 <lyxia> that wouldn't be sufficient
14:11 <lyxia> it just defines a function named map
14:11 <stevenxl> OK. Thank you. I'll stick with checking the results then.
14:11 <stevenxl> ;-)
14:12 <lyxia> the fact that it typechecks does give you some level of assurance but it's not complete
14:12 Gentilhomme joined
14:12 <lyxia> :t \f -> foldr ((:) . f) []
14:12 <lambdabot> Foldable t => (a1 -> a) -> t a1 -> [a]
14:16 ner0x652 joined
14:16 fizruk joined
14:17 epsilonhalbe joined
14:17 epsilonhalbe left
14:20 fotonzade joined
14:22 oisdk joined
14:23 persona_ingrata joined
14:29 carlosdagos joined
14:29 Rizy joined
14:30 revprez joined
14:30 orphean joined
14:37 wtetzner joined
14:41 alx741 joined
14:41 grayjoc joined
14:42 spatial joined
14:42 <spatial> let result = (y == fromIntegral( round y)) should return True if y is 0,5 ?
14:42 fizruk joined
14:42 <spatial> False
14:43 puregreen joined
14:43 <spatial> I get True. I think.
14:44 sanett joined
14:45 <lyxia> > round 0.5
14:45 <lambdabot> 0
14:45 bxc joined
14:45 <lyxia> That's not equal to 0.5
14:47 <spatial> I am trying to do this http://clhs.lisp.se/Body/f_inte_1.htm
14:47 osa1 joined
14:48 <spatial> lyxia: You mean that code will return False if it is 0.5?
14:50 <lyxia> Yeah
14:53 cyborg-one joined
14:53 theelous3 joined
14:56 JuanMiguel joined
14:58 halogenandtoast joined
14:58 <unknownln> > map round [0.5, 1.5, 2.5, 3.5]
14:58 <lambdabot> [0,2,2,4]
14:58 <halogenandtoast> So this is probably impossible, but there isn't a function in Haskell the recurses with the same exact arguments is there?
14:59 enitiz joined
14:59 <halogenandtoast> for instance is the user selected an invalid option and I want to make them chose again.
14:59 <halogenandtoast> s/is the user/if the user/
14:59 <unknownln> You can do that, it'd just be in IO
15:00 <halogenandtoast> I'm already in IO
15:00 <unknownln> Read a line, if it's right call a different function, otherwise call the function you're in again with the same arguments
15:00 <halogenandtoast> unknownln: yes
15:01 bungoman_ joined
15:01 <unknownln> I'm saying that's what you should do :p
15:01 <unknownln> Let me get to a computer, I can write an example
15:01 codesoup joined
15:01 <halogenandtoast> unknownln: Oh I'm doing that
15:01 <halogenandtoast> I just wondered if there was a "magical" way to recurse without having to pass that options
15:01 <halogenandtoast> basically
15:01 <unknownln> Oh, then what's the problem?
15:01 <halogenandtoast> maybe (myFun arg1 arg2) return maybeVal -> maybe magicFunc return maybeVal
15:02 <unknownln> Yeah there is
15:02 <unknownln> One sec
15:02 j_king joined
15:03 gpbaran joined
15:03 <mauke> just give your body a name
15:04 <mauke> myFun arg1 arg2 = magicFunc where magicFunc = do ...
15:04 dawehner joined
15:05 <unknownln> https://hastebin.com/ejubahowux.hs for an extended example
15:05 <halogenandtoast> right, makes sense
15:05 AX3L joined
15:05 Apocalisp joined
15:06 ziocroc joined
15:06 <mauke> myFun arg1 arg2 = fix $ \magicFunc -> do ...
15:06 <halogenandtoast> mauke: yeah I knew about fix, didn't think to appy it here
15:07 <unknownln> wow, I always forget about fix
15:08 e14 joined
15:09 augur joined
15:09 <orion> Is it legitimate for me to call "Maybe a" a co-product of Unit and a?
15:09 <cocreature> orion: sure
15:11 uglyfigurine joined
15:11 sanett joined
15:11 <glguy> halogenandtoast: It's common to see: f x y = go where go z = ...
15:11 Claudius1aximus joined
15:12 <halogenandtoast> glguy: yeah
15:12 <halogenandtoast> thanks!
15:16 route joined
15:17 mkoenig joined
15:19 DataComputist1 joined
15:19 Welkin joined
15:20 cloudhead joined
15:21 oisdk joined
15:21 cur8or joined
15:22 danharaj joined
15:22 {emptyset} joined
15:25 petervaro joined
15:25 theelous3 joined
15:26 sanett joined
15:27 <centril> with stack ghci, after changing the dependencies in <xyz..>.cabal , how do I reload with these dependencies ?
15:27 <centril> so that I dont have to quit ghci first
15:28 <cocreature> centril: I don’t think you can.
15:28 <centril> cocreature: :/
15:28 <centril> cocreature: what about doing it with :! ?
15:28 <centril> (to execute arbitrary shell commands)
15:28 <cocreature> I don’t see how that helps
15:29 <centril> crap
15:29 <cocreature> if you just added a package you might be able to get away with ":set -package packagename"
15:29 <cocreature> but I don’t know if you can remove packages this way
15:29 <centril> cocreature: ill try that - since it is mostly the cause
15:29 <centril> cocreature: i very rarely remove packages, it is mostly adding a package after a branching or something
15:29 jeltsch joined
15:30 <cocreature> you will also need to build the package, i.e., run "stack build" before you execute that
15:30 carlosdagos joined
15:30 <centril> right, atm I just pop out of stack ghci and then reenter it
15:31 <centril> I guess I could alias an action to 1) stack build 2) :set -package <name>
15:34 adraenwan joined
15:35 xinming joined
15:37 t0by joined
15:37 t0by joined
15:39 owiecc joined
15:40 grayjoc joined
15:42 fabianhu joined
15:44 <Athas> Is there a way for a Haskell program to ask the runtime never to use more than one thread for garbage collection?
15:44 <Athas> The overhead of parallel GC is pretty silly.
15:44 Cthalupa joined
15:44 grayjoc joined
15:45 windsing joined
15:45 uglyfigurine joined
15:48 afnizarnur joined
15:48 afnizarnur left
15:48 afnizarnur joined
15:49 enitiz joined
15:49 afnizarnur left
15:49 dawehner joined
15:52 UberLambda joined
15:52 sepp2k joined
15:53 <c_wraith> Athas: yes, you can disable parallel gc
15:53 <Athas> c_wraith: how so?
15:53 connrs joined
15:53 <c_wraith> Some RTS option or another.
15:53 chewzerita joined
15:54 <c_wraith> looks like -qg turns off parallel gc
15:55 <Athas> Right, but I don't want to do this with an RTS option. I want the program itself to disable parallel GC (without the user having to care about it).
15:55 <Athas> I guess I can modify the build flags, though.
15:55 <mauke> shell script wrapper
15:56 <chewzerita> Is there any way to make an Applicative instance of a tree? `data Tree a = Empty | Node a (Tree a) (Tree a)` I am following the learn you a haskell book, but I can't seem to figure this out
15:56 <c_wraith> chewzerita: you can! What difficulty are you having?
15:56 <chewzerita> I'll show you what I have so far..
15:56 <Athas> I'm already using -with-rtsopts=-N, and I guess I can add -with-rtsopts=-qg to that.
15:56 <halogenandtoast> Which of these is more idiomatic?
15:57 <lpaste_> halogenandtoast pasted “Idiomatic.hs” at http://lpaste.net/353713
15:57 <chewzerita> @c_wraith I have the functor instance done: fmap _ Empty = Empty, fmap f (Node x a b) = Node (f x) (fmap f a) (fmap f b)
15:57 <lambdabot> Unknown command, try @list
15:57 <c_wraith> halogenandtoast: both are pretty common. I don't think I'd prefer one over the other.
15:58 <c_wraith> chewzerita: can you put code on lpaste.net ? It's much easier to read formatted there.
15:58 <chewzerita> @c_wraith sure, that sounds better
15:58 <lambdabot> Unknown command, try @list
15:58 <Welkin> chewzerita: don't prefix names with @ on IRC
15:58 <Welkin> just type the name alone
15:58 <Athas> Is there a way to share Ghc-Options between several Executable-targets in a .cabal file?
15:59 <Welkin> chewzerita: otherwise you will trigger lambdabot
15:59 <halogenandtoast> c_wraith: thanks, not the answer I was hoping for, but an answer none the less.
16:00 pinupgeek_ joined
16:00 <MarcelineVQ> it's good new though, if you were hoping for one specifically then you can just use that one
16:00 <spatial> IO (BoardState,IOArray Int Double) How to get BoardState if return type is this ?
16:00 Cthalupa joined
16:00 afnizarnur joined
16:00 <spatial> Can I unwrap it ?
16:00 <Athas> spatial: pattern-matching.
16:01 <mauke> spatial: only locally
16:01 <chewzerita> c_wraith: http://lpaste.net/353714
16:01 <halogenandtoast> MarcelineVQ: I wasn't hoping for one in particular, I just wanted one to be preferential
16:01 BusFactor1 joined
16:01 <Athas> (the_boardstate, _) <- theComputationProducingThatPair
16:01 <mauke> spatial: do { (bs, _) <- stuff; ... }
16:01 <halogenandtoast> chewzerita: x a and b aren't the same types, so I assume you can't call the same f on them
16:01 jsoo joined
16:02 <halogenandtoast> x is an a, but a and b are Tree a
16:02 <MarcelineVQ> Athas: possibly somewhere in new features, not that I know of though, some people use hpack for that https://github.com/sol/hpack#readme
16:02 moth joined
16:02 <c_wraith> chewzerita: hah. oops. I was totally wrong. There's no simple way to make that Applicative. (I was thinking about Traversable for some reason.)
16:03 <c_wraith> chewzerita: The problem you're running into is that you have no guarantee the trees will be the same shape, and no obvious right thing to do when they aren't, right?
16:03 afnizarnur joined
16:03 <chewzerita> c_wraith: that makes sense
16:03 connrs joined
16:03 <halogenandtoast> chewzerita: ignore me, I derped on fmap
16:03 <Athas> MarcelineVQ: thanks, looks like that's the most reasonable option. I have seven executable targets by now and the hand-maintenance is getting to be a bit much...
16:04 <chewzerita> c_wraith: does that mean this tree is only a functor?
16:05 robotroll joined
16:06 Fairy joined
16:06 <c_wraith> chewzerita: Well, it's certainly a Functor. I'm not 100% sure you *can't* create an Applicative instance, but it certainly isn't an obvious thing
16:06 allenj12 joined
16:06 gpbaran joined
16:06 <chewzerita> c_wraith: alright, thanks for the help. I'm having great fun learning this language
16:07 peterbecich joined
16:07 <c_wraith> chewzerita: actually, I *can* create an Applicative instance, kind of like the Applicative instance for ZipList - but it's weird and probably not something you'd want to use. :)
16:07 peterbec` joined
16:08 <c_wraith> chewzerita: I'll write it up quickly and you can see why I call it weird. :)
16:08 dawehner joined
16:08 <mauke> it would be easier with a different type of tree
16:08 <mauke> data LTree a = Leaf a | Node (LTree a) (LTree a)
16:10 <halogenandtoast> mauke: doesn't that still need an Empty?
16:10 <mauke> does it?
16:11 <chewzerita> mauke: I acually had the same tree before. I did make an Applicative instance for it
16:11 <halogenandtoast> mauke: How would you represent a tree with no nodes or values?
16:11 <mauke> I wouldn't
16:12 <chewzerita> mauke: but it wasn't really a tree because the nodes didn't have values in them, only the leafs
16:12 <halogenandtoast> What about a tree with only a left, but no right?
16:12 arawack joined
16:12 <orion> I'm watching a video lecture series on category theory for Haskell programmers. The speaker said that all data are functions and all functions are data. How is a data type a function?
16:12 <mauke> halogenandtoast: nope
16:12 <halogenandtoast> mauke: I don't like your tree
16:12 <Welkin> orion: it's not
16:12 <mauke> orion: the speaker is wrong
16:12 <mauke> halogenandtoast: but it's a monad
16:13 <halogenandtoast> I've learned that not all things that are monads are useful, and not all things that are useful are monads
16:13 <orion> Oh wow
16:13 <MarcelineVQ> chewzerita: What section is this exercise in?
16:13 connrs joined
16:13 <c_wraith> chewzerita: http://lpaste.net/353716
16:13 <orion> Welkin / mauke: His name is Bartosz Milewski.
16:14 t0by joined
16:14 <c_wraith> chewzerita: the only reason that works is because pure creates an infinite tree
16:14 <c_wraith> chewzerita: which is a bit silly
16:15 <chewzerita> MarcelineVQ: http://learnyouahaskell.com/functors-applicative-functors-and-monoids http://learnyouahaskell.com/making-our-own-types-and-typeclasses#recursive-data-structures
16:15 <Welkin> orion: 1 is not a function
16:15 <halogenandtoast> c_wraith: you don't need to do that
16:15 <Welkin> orion: neither is "hello"
16:15 <chewzerita> MarcelineVQ: it shows up in two sections
16:15 <MarcelineVQ> chewzerita: thank you
16:15 sanett joined
16:15 <c_wraith> halogenandtoast: how else do you satisfy the applicative laws?
16:16 Fairy joined
16:16 BusFactor1 joined
16:16 <jgt> is there a better way to write this function? http://sprunge.us/FSiP
16:16 <halogenandtoast> c_wraith: annotated, but I might be breaking a law
16:16 <jgt> I feel like that function shouldn't even exist
16:16 <halogenandtoast> if I am, I'm interested in which one.
16:16 <Welkin> jgt: lol sprunge? Use lpaste :D
16:16 <Welkin> @lpaste
16:16 <lambdabot> Haskell pastebin: http://lpaste.net/
16:17 <chewzerita> c_wraith: why did you do "let result = X in result" instead of just "X"
16:17 <halogenandtoast> jgt: you could use `either`
16:17 <c_wraith> halogenandtoast: your example breaks pure id <*> x = x
16:17 JoeyAdams joined
16:17 <jgt> Welkin: I have sprunge hooked up to my command line so I can just send it stuff from vim
16:17 <mauke> :t either (const []) id
16:17 Fendor joined
16:17 <lambdabot> Either b [t] -> [t]
16:17 <jgt> halogenandtoast: I thought I could, but I'm not quite sure how
16:17 <jgt> ohhh…
16:17 <jgt> right
16:17 <c_wraith> chewzerita: because the expression X uses result internally
16:17 <halogenandtoast> everyoe forgets const
16:17 DataComputist1 joined
16:17 <mauke> :t either (pure []) id
16:17 <lambdabot> Either a [t] -> [t]
16:18 Fendor joined
16:18 <chewzerita> c_wraith: that is what makes is infinite, I get it now
16:18 <jgt> thanks folks
16:18 <c_wraith> chewzerita: exactly
16:18 <mauke> :t either (pure (fail [])) ask
16:18 <lambdabot> Monad m => Either a (m a1) -> m a1
16:18 <halogenandtoast> c_wraith: thanks I'll try it out
16:19 <chewzerita> c_wraith: Thanks a ton!
16:19 <c_wraith> chewzerita: you're welcome.
16:20 uglyfigurine joined
16:20 <JoeyAdams> I've been largely out of the Haskell loop for a few years. The Haskell website offers 3 options for installing (Minimal, Stack, or Platform). Would Platform typically be recommended for people new to Haskell who want to learn, while Stack would be a better choice for more advanced users who already have projects with dependencies they want to maintain?
16:21 <orion> Welkin: https://youtu.be/EO86S2EZssc?t=47m18s <-- "The distinction between a function and a data type is weak."
16:21 <halogenandtoast> JoeyAdams: I'd suggest stack no matter what
16:21 <Theophane> JoeyAdams: I'm not an advanced user, but I think Stack is the best option
16:22 sanett_ joined
16:22 <bxc> stack is easy enough to start with and is going to put you in the right place when you want to level up
16:22 <halogenandtoast> But I'm a huge derp who doesn't get his applicative laws correct.
16:22 <orion> And at 48:38 he says, "So, data are really functions. Functions are really data. There really is no hard core distinction."
16:23 <orion> bxc: What would "leveling up" consist of?
16:23 C-16 joined
16:23 mson joined
16:24 urodna joined
16:24 <halogenandtoast> orion: That could be true in lamdba calculus right?
16:24 tomphp joined
16:25 <orion> halogenandtoast: Except the speaker is talking about Haskell.
16:25 a3Dman joined
16:26 <cocreature> orion: I think haskell as a language has a hard distinction. something of type a -> b is a function, everything else is not
16:26 <cocreature> orion: he seems to be arguing that computationally data and functions are similar
16:26 <halogenandtoast> c_wraith: can you explain how that infinite expansion of pure works
16:27 <halogenandtoast> I can't seem to wrap my head around it
16:27 raycoll joined
16:27 <c_wraith> halogenandtoast: it creates a Node whose child pointers point to itself.
16:27 <c_wraith> halogenandtoast: in memory, it actually is a circular structure.
16:27 nothingnew joined
16:28 raycoll joined
16:28 <bxc> orion: starting to use the stuff that stack does well - mostly in my practical use that is fiddling with different library versions and having it rebuild right with one command
16:28 sanett joined
16:29 decaf joined
16:29 baroncharlus joined
16:29 <c_wraith> halogenandtoast: so whenever you get one of the child values, you are actually getting the same value
16:29 <JoeyAdams> On Stackage, they have "snapshots" like this one: https://www.stackage.org/nightly-2017-03-19 . Is it possible to download a manifest of the snapshot as a text file?
16:30 <c_wraith> halogenandtoast: the general approach is called knot-tying, if you want to look into it further.
16:30 <halogenandtoast> c_wraith: okay so `print $ (pure 1 :: Tree Int)` results in terribleness then
16:30 <c_wraith> halogenandtoast: well, it "works" in some sense. How long *should* it take to print an infinite value? :)
16:30 <bxc> JoeyAdams: so that you can write your own bad implementation of stack? Someone had a tool on r/haskell recently that did something in that direction recently, but I can't remmeber offhand
16:30 <c_wraith> halogenandtoast: but yes, it will never finish printing it
16:31 carlosdagos joined
16:31 <c_wraith> halogenandtoast: I need to run now. Lots of people can help with knot-tying, though
16:31 <JoeyAdams> I was just curious, really. Seeing a big yaml file of the whole snapshot would help me understand what exactly goes into a Stack "snapshot" (though I might be mixing up Stack and Stackage).
16:32 iomonad joined
16:32 <halogenandtoast> c_wraith: no problem, thanks for the help
16:32 Adios joined
16:34 albertus1 joined
16:35 conal joined
16:35 afnizarnur left
16:36 moongazer joined
16:36 doodlehaus joined
16:36 erisco joined
16:37 fotonzade joined
16:37 <erisco> ertes, there is way too much hype about undecidability
16:38 <erisco> oh it is undecidable, guess we have to do something else
16:39 <erisco> well no, you just can't have one program that solves everything
16:39 <erisco> that is just one exclusion in a sea of possibilities
16:40 JagaJaga joined
16:40 sanett joined
16:40 <erisco> the real answer is, that is what we do as programmers all the time
16:40 <erisco> there is no one program to solve everything and so we have to take smaller programs and stick them together in new ways
16:41 <erisco> if automation was the only solution then fine, alright, but I don't think it usually is
16:41 <maerwald> in what context are you arguing?
16:41 oisdk joined
16:41 <erisco> I am replying to what ertes said 14 hours ago
16:42 phyrex1an joined
16:42 robkennedy joined
16:43 doodlehaus joined
16:43 robkennedy joined
16:44 fizruk joined
16:44 nomicflux joined
16:45 robertkennedy joined
16:48 coltfred joined
16:51 SpinTensor joined
16:52 windsing joined
16:54 uglyfigurine joined
16:56 dawehner joined
16:57 eazar001 joined
16:58 mac10688 joined
17:01 mangobo joined
17:02 <mangobo> http://pastebin.com/dcRHhZc8 could someone help me with thw invariant for the while loop? i know it should hold for every iteration, but not sure which one would work for this function
17:02 MP2E joined
17:02 <Welkin> mangobo: that isn't haskell
17:03 <halogenandtoast> Any good way to debug when I get crazy output with `Undefined symbols for architecture x86_64`
17:03 mohsen_ joined
17:03 <Welkin> halogenandtoast: linker error
17:04 <Welkin> you probably need to include the libraries you are using with the -l flag
17:04 <Welkin> how are you bulding?
17:04 <Welkin> building*
17:04 <halogenandtoast> `stack build`
17:04 <Welkin> what does your build command look like?
17:04 <Athas> Hm, hpack seems really good. Much nicer than Cabal.
17:04 <Theophane> mangobo: the hell is that language?
17:04 mangobo left
17:05 <halogenandtoast> Welkin: I'm not sure what you're asking for
17:05 <halogenandtoast> Do you mean this: `/Users/matthew-mongeau/.stack/setup-exe-cache/x86_64-osx/Cabal-simple_mPHDZzAJ_1.24.2.0_ghc-8.0.2 --builddir=.stack-work/dist/x86_64-osx/Cabal- build lib:battleline exe:battleline --ghc-options " -ddump-hi -ddump-to-file"`
17:05 <Welkin> halogenandtoast: the actual command that gets run `ghc ...`
17:06 <Welkin> I've encountered this issue before when compiling c with opengl/sdl
17:06 JuanMiguel joined
17:06 <Welkin> halogenandtoast: any external libs you are using?
17:07 <halogenandtoast> No just a lib I wrote in my project
17:07 <halogenandtoast> So I have a lib + exec stup
17:08 Fendor joined
17:08 peterbecich joined
17:08 peterbec` joined
17:09 anton joined
17:10 marfoldi joined
17:10 a3Dman joined
17:10 <halogenandtoast> Welkin: looks like I wasn't exporting a module
17:10 <halogenandtoast> womp womp
17:11 pie__ joined
17:11 <Welkin> I was just going to ask if you included all of the files
17:11 <Welkin> lol
17:11 dan_f joined
17:11 <Welkin> I know there is an actual way to debug this using `ld`
17:11 <Welkin> geekosaur showed me a while back when I ran into trouble
17:12 baroncharlus joined
17:13 kthnnlg joined
17:15 <bxc> i fairly regularly get linker problems with stack with an old lts (3.20) that are cleared away with a `stack clean`. I've never delved into what causes it though
17:15 <bxc> or rather it wasn't apparent in the ten mins or so I spent on it
17:16 meba joined
17:16 falafel joined
17:18 cschneid_ joined
17:19 mmachenry joined
17:19 oberstein joined
17:21 pita joined
17:21 IRCFrEAK joined
17:22 zennist joined
17:24 conal joined
17:25 descender joined
17:26 cfricke joined
17:26 Lazersmoke joined
17:27 sphinxo joined
17:28 ralu joined
17:28 fizruk joined
17:29 begriffs joined
17:29 uglyfigurine joined
17:30 <halogenandtoast> Is there something that already does this: `replace old new = map (\x -> if x == old then new else x)
17:31 caasih joined
17:31 carlosdagos joined
17:34 eacameron joined
17:34 oisdk_ joined
17:35 gpbaran joined
17:36 e14 joined
17:37 bungoman joined
17:38 <liste> @hoogle Eq a => a -> a -> [a] -> [a]
17:38 <lambdabot> Network.CGI.Protocol replace :: Eq a => a -> a -> [a] -> [a]
17:38 <lambdabot> Data.List.Utils replace :: Eq a => [a] -> [a] -> [a] -> [a]
17:38 <lambdabot> Data.String.Utils replace :: Eq a => [a] -> [a] -> [a] -> [a]
17:38 barryburd joined
17:38 <liste> ^ halogenandtoast so apparently not in base
17:39 Glooomy joined
17:40 <halogenandtoast> Oh well
17:41 harfangk joined
17:41 mada joined
17:41 <michalrus> How can I force `hlint` to be run at each `stack build`? (:
17:42 <Gurkenglas> :t each . from (non ?old) %~ (<|> Just ?new)
17:42 <lambdabot> (?old::a, ?new::a, Eq a, Each s t a a) => s -> t
17:42 <michalrus> But just `stack build`, not `stack install hlint` (polluting global ~/.local/bin…) and `stack build --exec 'hlint src'`…
17:42 <bollu> :t from
17:42 <lambdabot> (Functor f, Profunctor p) => AnIso s t a b -> p t (f s) -> p b (f a)
17:43 <bollu> Gurkenglas: example use of "from"?
17:43 raycoll joined
17:43 ameivq joined
17:44 <Gurkenglas> How about a property? from (iso f g) == iso g f
17:46 <liste> michalrus: see "Static Analysis" here http://taylor.fausak.me/2014/03/04/haskeleton-a-haskell-project-skeleton/
17:46 <michalrus> liste: thank you!
17:46 <liste> michalrus: you're welcome
17:46 fabianhu joined
17:47 tromp joined
17:47 <lpaste_> halogenandtoast pasted “Update.hs” at http://lpaste.net/353719
17:47 <halogenandtoast> Any ideas on how to make that better ^^
17:48 <halogenandtoast> in particular I don't like the duplication in the case
17:49 yellowj joined
17:55 <lyxia> halogenandtoast: first overwire the common fields in the where clause
17:55 revtintin joined
17:55 <lpaste_> lyxia annotated “Update.hs” with “Update.hs (annotation)” at http://lpaste.net/353719#a353720
17:57 <halogenandtoast> lyxia: Right, not sure why I didn't think of that
17:57 <halogenandtoast> I plan tiredness
17:57 <halogenandtoast> s/plan/blame/
17:57 <halogenandtoast> O_o
17:57 <lyxia> I can see that :D
17:57 <halogenandtoast> In all fairness, it's 3am here.
18:02 desktop joined
18:02 gpbaran joined
18:02 JuanMiguel joined
18:03 yianni joined
18:03 conal joined
18:04 uglyfigurine joined
18:04 doodlehaus joined
18:07 Ayey_ joined
18:07 mac10688 joined
18:10 mfukar joined
18:11 ertesx joined
18:12 oisdk joined
18:17 uglyfigurine joined
18:18 <halogenandtoast> is there any way to combine this let (cards, deck') = draw 7 deck; let (cards', deck'') = draw 7 deck'
18:18 tomphp joined
18:19 <halogenandtoast> so that I get (cards, cards', deck'') as the result
18:19 <erisco> let ... in let ... in ...
18:19 <erisco> which simplifies to let ... ... in ...
18:20 <halogenandtoast> Hmm I was hoping to do something super crazy like (,,) <$> draw 7 <*> draw 7 deck
18:20 <halogenandtoast> I know that doesn't work
18:20 <halogenandtoast> but that's the structure I was hoping for
18:21 <Rotaerk> halogenandtoast, if you treated it as State Deck T, you could do: do { cards <- draw 7; cards' <- draw 7; ... }
18:21 <geekosaur> that pattern is closer to a state monad
18:21 <erisco> :t unfoldr
18:21 <lambdabot> (b -> Maybe (a, b)) -> b -> [a]
18:22 fendoer joined
18:22 <halogenandtoast> hmm I've never use the state monad
18:22 <nshepperd> runState ((,,) <$> draw 7 <*> draw 7) deck
18:22 <halogenandtoast> I'd assume I'd need some function like `runDeck` then?
18:22 <halogenandtoast> runState
18:23 <erisco> well the state monad is not going to help much
18:23 <erisco> oh I misunderstood, the state is the deck, not the cards
18:24 <Rotaerk> also I should've said State Deck a; I used T like this was C# >_>
18:24 <halogenandtoast> Rotaerk: tis alright, I understood
18:26 coot joined
18:27 <Rotaerk> draw would change from a Int -> Deck -> ([Card], Deck) to a Int -> State Deck [Card]
18:28 crobbins joined
18:29 shayan_ joined
18:29 <erisco> then you want it to be SNat n -> Deck m -> (Deck (m :-: n), [Card])
18:29 <erisco> where are my manners
18:29 <erisco> then you want it to be SNat n -> Deck m -> (Deck (m :-: n), Vec n Card)
18:30 <halogenandtoast> O_o
18:30 cyborg-one joined
18:30 oish joined
18:30 <halogenandtoast> That quickly went from something I thought I could understand to something out of my league
18:31 <erisco> but then you realise you can't implement that because you forgot m >= n
18:31 <erisco> so you add n :<=: m to the parameters
18:32 carlosdagos joined
18:33 <erisco> halogenandtoast, it adds how many cards are in the deck and how many you draw to the types
18:33 oisdk joined
18:33 AX3L joined
18:34 dibblego joined
18:34 nomotif joined
18:34 <halogenandtoast> erisco: that sounds awesome, and I really want to get to the point where I understand that, but I don't think I understand enough to make runState ((,,) <$> draw 7 <*> draw 7) deck work
18:35 <halogenandtoast> pending it's even possible to make that work
18:35 Zekka joined
18:35 <erisco> I was joking
18:35 <erisco> you can do it, but I wouldn't consider it practical, not in Haskell anyways
18:37 robertkennedy joined
18:37 <robertkennedy> @hoogle Int -> [Bool]
18:37 <lambdabot> Music.Theory.Bjorklund iseq :: [Bool] -> [Int]
18:37 <lambdabot> Data.List.HT lengthAtLeast :: Int -> [a] -> Bool
18:37 <lambdabot> Data.Edison.Seq.ListSeq inBounds :: Int -> [a] -> Bool
18:39 ragepandemic joined
18:41 <erisco> hm, that's not even everything you'd want to say either
18:41 <erisco> you want to also have that the drawn cards come from the deck
18:42 poop joined
18:42 eacameron joined
18:42 allenj12 joined
18:45 muesli4 joined
18:46 cschneid_ joined
18:46 mac10688 joined
18:46 silver joined
18:47 pera joined
18:48 systemfault joined
18:49 <halogenandtoast> erisco: You can do it! Show me your types!
18:49 <erisco> uh, well you need singleton lists
18:50 <halogenandtoast> *sigh* how do I get this line to compile! let (cards, cards', deck'') = runState ((,,) <$> draw 7 <*> draw 7) deck
18:50 <halogenandtoast> Couldn't match expected type ‘(t2, t1, t)’ with actual type ‘(c0 -> ([Card], [Card], c0), Deck)’
18:50 <halogenandtoast> I'm not even sure how to read that error
18:51 <erisco> the pattern on the left has type (t2, t1, t)
18:51 <Welkin> it expects a tuple
18:51 <erisco> the thing on the right has type (c0 -> ([Card], [Card], c0), Deck)
18:51 <Welkin> you have a tripple, to start
18:51 <Welkin> triple*
18:51 <Rotaerk> try: let (cards, cards') = runState ((,) <$> draw 7 <*> draw 7) deck
18:51 <erisco> tuples are not just pairs
18:52 <Rotaerk> err
18:52 <bollu> erisco: ?
18:52 <Rotaerk> let ((cards, cards'), deck') = ...
18:52 <erisco> (,,) constructs a tuple
18:52 <erisco> they are 2-tuples, 3-tuples, and so on
18:52 <Rotaerk> it's the wrong tuple; it should be (,) since he's only collecting two sets of cards
18:52 aarvar joined
18:52 <erisco> yes, it is, I am just rectifying the terminology
18:52 mexisme joined
18:53 <Rotaerk> k
18:53 <halogenandtoast> Rotaerk: yes after fixing (,) and the left hand side it works, now I guess I should pay attention to how to read that error
18:53 windsing joined
18:53 <halogenandtoast> erisco: right, I'm aware of n-tuples
18:54 <halogenandtoast> okay yup
18:54 <halogenandtoast> I can read it now
18:55 chaosmasttter joined
18:55 <dmwit_> robertkennedy: Possibly:
18:55 chenyu joined
18:55 <dmwit_> :t showIntAtBase
18:55 <lambdabot> (Show a, Integral a) => a -> (Int -> Char) -> a -> ShowS
18:55 <dmwit> robertkennedy: But it depends on what you want that function to do, really.
18:56 <halogenandtoast> so holy crap, I've used the State monad and it works, (and by works I mean it compiles)
18:56 <dmwit> robertkennedy: Or you might like the `Bits` instance for `Int`.
18:56 vaibhavsagar joined
18:56 <halogenandtoast> and it actually works
18:56 <halogenandtoast> what a lovely day
18:56 Gurkenglas joined
18:57 <halogenandtoast> thans Rotaerk, erisco, Welkin, and others
18:57 <halogenandtoast> *thanks
18:57 <Rotaerk> np
18:57 cschneid_ joined
18:57 oberstein joined
18:58 yellowj joined
18:58 shane joined
18:58 <halogenandtoast> okay it's 4am, I should probably sleep since that's something humans need to do usually
18:59 <Rotaerk> you mean you don't get sufficient rejuvenation from using haskell?
19:00 <halogenandtoast> Apparently not
19:00 <halogenandtoast> I'm so tired I feel like I'm slightly drunk without having drank.
19:02 nomicflux joined
19:02 <Jello_Raptor> I am an idiot >_< I keep on using `flip mapM` as an idiom in my code and had no idea `forM` existed
19:02 <lyxia> for is even shorter
19:02 <monochrom> To be fair, forM requires one more import.
19:03 daan joined
19:03 <bollu> lyxia: for gives applicative power right, forM is monadic?
19:03 <monochrom> @type for
19:03 <lambdabot> (Applicative f, Traversable t) => t a -> (a -> f b) -> f (t b)
19:03 msko joined
19:04 <monochrom> yeah
19:04 <Jello_Raptor> but the monad constraint is an artifical restriction
19:04 <monochrom> forM doesn't need all of monadic power.
19:04 byte512 joined
19:05 dan_f joined
19:05 <Tuplanolla> Does `ApplicativeDo` work yet?
19:05 augur joined
19:06 <lyxia> It does work
19:06 jeltsch joined
19:07 <Jello_Raptor> oh it's in GHC 8 now
19:07 <* Jello_Raptor> goes to turn it on in his cabal files
19:08 <Tuplanolla> I ask, because when it was introduced a simple use of `$` broke it.
19:08 <Jello_Raptor> mmm?
19:08 <lyxia> okay well this is still "broken"
19:08 <* Jello_Raptor> comments out those lines
19:09 <Jello_Raptor> how is it broken?
19:09 <centril> For a record data type for which Show is derived, is it possible to get an alternate function (to show) which yields a result as-if the data type were not a record ?
19:09 <Jello_Raptor> or more accurately how does "$" break it?
19:09 _sg joined
19:09 <centril> and by get i mean: i dont want to write it myself
19:09 <lyxia> so to use applicative your program must look like this do { a <- stuff ; b <- stuff ; return (f a b) }
19:09 mizu_no_oto joined
19:09 peterbecich joined
19:09 peterbec` joined
19:10 <lyxia> Jello_Raptor: but if you write return $ f a b instead it doesn't desugar the way you expect it to
19:10 <Jello_Raptor> ahh :/
19:10 <Tuplanolla> :t \ m -> do {x <- m; pure $ x} -- So this was inferred as not applicative, Jello_Raptor.
19:10 <lambdabot> Monad m => m b -> m b
19:10 <centril> I always avoid using return
19:10 <mohsen_> Hi. I define 3 functions as : let f 0 = "zero" , let f 1 = "one", let f x = "unknown"
19:10 <Welkin> why?
19:10 <mohsen_> But whatever I input I get unknown
19:11 <mohsen_> No matter if I use _ instead of x
19:11 <Welkin> mohsen_: you are writing it wrong
19:11 <centril> Welkin: pure is both shorter, to the point and relaxes constraints
19:11 <lyxia> it's a pretty minor annoyance though.
19:11 <Tuplanolla> How so, lyxia? It fails for other such combinators too.
19:11 <Welkin> > let f 0 = "zero"; f 1 = "one"; f x = "unknown" in f 0
19:11 <lambdabot> "zero"
19:13 <mohsen_> Why doesn't it work that way in ghci?
19:13 <Welkin> mohsen_: it does
19:13 <Welkin> let creates a temporary binding
19:13 <barrucadu> I find how heavily ApplicativeDo is based on your code being of a certain form pretty unsatisfactory, but I have no idea how hard doing it "properly" (so that any do-block which could be Applicative is) would be
19:13 <Welkin> if oyu want to define a function, write it in a file the proper way
19:14 <Welkin> and use `:load` to load the file in ghci
19:14 <orion> If I have a function f :: Int -> Bool, for all intents and purposes, could I consider f to be a functor from the "Int" category (where each integer is an object) to the Bool category (where True and False are objects)?
19:14 <Athas> Has anyone here switched from .cabal files to package.yaml, and what were your experiences?
19:14 <mohsen_> Welkin: You mean when I define a function using let in ghci, then I define the same function again with a different pattern, always the last one is known?
19:14 <orion> Athas: Yes, many times, and it's worth it.
19:14 <centril> Athas: package.yaml ?
19:14 <orion> centril: hpack
19:14 buttons840 joined
19:15 <barrucadu> orion: That could be the object function of a functor, but functors also map morphisms.
19:15 <Athas> orion: that was also my impression, but nothing's ever so painless in packaging, so now I'm wondering what I missed!
19:15 <barrucadu> So you'd also need a function :: (Int -> Int) -> (Bool -> Bool), which preserved id and composition
19:15 <centril> oh cool
19:15 <Athas> centril: from hpack. It's another format for describing Haskell packages. In essence, it's a .cabal file generator.
19:15 <centril> i dislike .yaml tho
19:15 <Athas> Yeah, .yaml isn't my favourite either. But it's better than .cabal!
19:15 <centril> Athas: yeah, thats true
19:16 <Athas> I'm willing to accept the colour of this bikeshed, because at least it does not leak.
19:16 <centril> Athas: do i have to have both stack.yaml and package.yaml then ?
19:16 <Welkin> Athas: "what colour is your bikeshed", the best-selling novel by Athas
19:16 <orion> centril: Yes.
19:16 <mohsen_> Welkin: Nevermind got my answer, thanks.
19:17 <centril> Welkin: is it about Wadler's Law ?
19:17 <centril> https://wiki.haskell.org/Wadler%27s_Law
19:17 meba joined
19:17 <lyxia> Tuplanolla: Doesn't return (...) look just fine
19:17 <orion> barrucadu: What if in the source category ("Int") I had no morphisms between distinct objects? I only had the identity morphism.
19:17 dennisvennink joined
19:18 <barrucadu> orion: Then I guess you could say that the arrow function of the funtor is implicit and just use `id`, but my category-fu is pretty weak so I don't know if that argument actually holds up
19:19 Glooomy joined
19:19 ccomb joined
19:19 <centril> so I can always write prettify :: String -> String ; prettify str = case parseExp str of ParseOk r -> prettyPrint res ; ParseFailed {} -> str --- which at least gives me indented records when used
19:19 <centril> but it still has the record names...
19:19 <centril> how do I get rid of them ?
19:20 <Welkin> centril: write your own pretty printer?
19:20 <Welkin> there may be an option somewhere
19:20 JuanMiguel joined
19:20 <centril> Welkin: well, I'm short on time
19:21 <Welkin> why would you want to get rid of the field names?
19:21 <Welkin> how would you know what data you are looking at?
19:21 <centril> Welkin: because: verbose output when debugging
19:21 eacameron joined
19:22 <centril> I just want to show a record data type as a plain data type
19:22 <centril> + indentation would be nice
19:22 Eagle_Erwin joined
19:22 <Welkin> centril: writing your own functions would be easy
19:22 <Welkin> throw together a parsec parser that operates on the output of "Show"
19:23 <Welkin> just remove everything after a comma and before a colon
19:23 <centril> Welkin: that simple ?
19:24 nomicflux joined
19:24 <centril> well, I guess I have to watch out for strings as well
19:24 <Welkin> it might be a little more work than that
19:24 <Welkin> but that's the basic idea
19:24 <Welkin> or you could operate on the pretty printer output instead
19:25 <centril> Welkin: indentation I know how to fix
19:25 <centril> Welkin: there isn't any existing package for this?
19:25 e14 joined
19:26 <Welkin> centril: there are lots of pretty printers
19:26 fabianhu left
19:26 <Welkin> some may have options
19:26 <centril> Welkin: right - the one I know of is haskell-src
19:26 dan_f joined
19:26 <centril> maybe you can point me in the right direction?
19:27 <joneshf-laptop> Didn't there used to be an `intercalate` or `intersperse` in `Data.Foldable`?
19:28 <centril> joneshf-laptop: Data.List
19:28 <centril> :h intercalate
19:29 <Welkin> intercalate *and* intersperse
19:29 <joneshf-laptop> So there wasn't one that only needed `Foldable f` not specifically list?
19:29 help2103980 joined
19:29 <help2103980> hello kind people
19:29 <help2103980> may I ask a question?
19:29 <help2103980> very basic one
19:29 anuxivm joined
19:30 <help2103980> since I just started today
19:30 <joneshf-laptop> Oh no, I'm thinking of PureScript.
19:30 <centril> joneshf-laptop: what does intersperse mean for an arbitrary Foldable ?
19:30 <joneshf-laptop> Sorry.
19:30 <centril> and not just lists
19:30 <centril> help2103980: shoot
19:30 <joneshf-laptop> centril, I never know which one is which, between `intercalate` and `intersperse`.
19:30 <help2103980> thanks @centril
19:30 <help2103980> so I have a list like so [1,1,1,1]
19:30 <Welkin> help2103980: no @ prefix
19:30 mathcass joined
19:31 <centril> joneshf-laptop: intercalate = concat . intersperse
19:31 <help2103980> i just want to increase the first value by one, the second by two, and so on
19:31 <help2103980> to obtain [2,3,4,5]
19:31 <dmwit> > zipWith (+) [1..] [1,1,1,1]
19:31 <lambdabot> [2,3,4,5]
19:31 <Welkin> > zipWith (+) [1,1,1,1] [1..]
19:31 <Welkin> lol
19:31 <lambdabot> [2,3,4,5]
19:31 <help2103980> lol
19:31 mathcass left
19:31 <help2103980> you people rock
19:32 <centril> Welkin: dude, lazy language
19:32 <centril> duuuude
19:32 <joneshf-laptop> centril, well you can definitely `intercalate` for an arbitrary `Foldable f`: https://pursuit.purescript.org/packages/purescript-foldable-traversable/2.2.0/docs/Data.Foldable#v:intercalate
19:32 <help2103980> I'll go and read about zipWith
19:32 <help2103980> thanks mates
19:32 Guest_ joined
19:33 <joneshf-laptop> centril, I just mixed up the languages, no worries!
19:33 carlosdagos joined
19:33 <centril> joneshf-laptop: right, using a monoid
19:34 <centril> you could also use join perhaps
19:34 <centril> depending on semantics
19:34 safe joined
19:35 <centril> help2103980: note: with zipWith [1..] xs where xs is a list, zipWith uses as many elements from [1..] as xs has
19:35 <centril> since it is a lazy infinite list
19:35 <centril> but:
19:35 <centril> > zipWith (+) [1, 2] [3]
19:35 <lambdabot> [4]
19:37 cschneid_ joined
19:37 <centril> help2103980: the length of the resulting list will be: min(length(first), length(second))
19:37 <dmwit> > let sum = head . zipWith (+) [18] in sum [1,5,10,3]
19:37 <lambdabot> 19
19:37 <dmwit> > 1 + 5 + 10 + 3
19:37 <lambdabot> 19
19:37 <Guest_> Debating implementing a Pymol clone in Haskell as a long term project.
19:38 Elish joined
19:39 <dylukes> One of the biggest issues I have with Pymol is the inability to go through a series of edits.
19:39 <dylukes> Does anyone have any suggested reading on persistent data structures with history?
19:40 oberstein joined
19:41 <dylukes> Naive approach would be to just keep a list of states but, wondering if there's any interesting reading on better approaches.
19:41 <Rembane> dylukes: How are you going to use the data structure?
19:41 AX3L joined
19:42 <dylukes> It's mostly a lot of settings, as well as some state which is used to generate a scene graph.
19:42 <Rembane> So you will always iterate through the whole data structure?
19:43 <dylukes> I'd like to update parts of the scene when their related parts of the underlying descriptive state change only when necessary, but yes, I'd probably just opt out early of the parts that don't need to be looked at.
19:43 <dylukes> There may be more than one renderer also.
19:43 <dylukes> But that should be a distinct concern.
19:44 ph88^ joined
19:44 <Rembane> I'd say, go for a list until things become slow.
19:44 <help2103980> I'm sorry people, but maybe my case is something else. I actually need to turn [[1,1,1],[1,1,1]] into [[2,2,2],[3,3,3]]
19:45 chaosmasttter joined
19:45 <ph88^> hi help2103980
19:45 <help2103980> adding 1 to every element of the first list and adding 2 to every element of the second list
19:45 danharaj joined
19:45 <help2103980> hi ph88^
19:45 <dylukes> Rembane I was thinking something like having ReaderT for accessing that state,
19:45 <ph88^> seems like you are not adding, but changing
19:45 <dmwit> help2103980: Use `map` in addition to `zipWith`, then.
19:45 <dmwit> help2103980: I encourage you to give it a shot before folks here give spoilers.
19:46 <dylukes> and just having an "markUndoPoint" function that stores a continuation in the state (session, really).
19:46 <dmwit> Show us what you tried and we can help you understand the error messages. ;-)
19:46 <dylukes> So then undo would be in a very literal sense rolling back the program, which would make things a bit easier.
19:46 <help2103980> yep dylukes
19:46 <orion> In this article: https://en.wikiversity.org/wiki/Introduction_to_Category_Theory/Monoids#Monoids they say, "For every pair of arrows f,g in M, the composition g .∘f of arrows is also in M" What does it mean to be *in* M? M is an abstract categorical object. How could there ever be any notion of "in"?
19:46 <Rembane> dylukes: Do you have a lot of functions accessing the state, so it becomes cumbersome to send it explicitly in an argument?
19:46 <dylukes> What do you mean?
19:46 <help2103980> I'm aware of map, which I was using in Python as well
19:47 <dylukes> Well, maybe.
19:47 a3Dman joined
19:47 bjz joined
19:47 <dylukes> I would probably just use ReaderT off the bat because I prefer a descriptive transformer stack to a lot of parameters.
19:47 <help2103980> but my problem was exactly storing the iteration state
19:47 e14 joined
19:47 <dmwit> orion: Without looking: presumably M is an object in the category, and "in M" means the arrow has type M -> M.
19:47 <dmwit> orion: Now I will look at the link.
19:48 <Rembane> dylukes: You could build yourself a transformer stack if that does what you want. I'd go for the naive approach until it's too slow or I got tired of threading arguments.
19:48 tromp joined
19:48 <dylukes> I could just mix ReaderT and ContT and add extra "undo" and "redo" functions.
19:48 <dmwit> orion: Yes, that is what they mean.
19:48 <dylukes> I have a feeling it's going to get slow very quickly :).
19:48 <tomboy64> i have a [[Int]] and i need to find the first repetition of [Int], meaning i need both indices. how would i accomplish this the smartest way?
19:48 alx741 joined
19:48 <dylukes> Er, not slow.
19:48 <dylukes> It's going to get frustrating to thread arguments quickly.
19:48 <tomboy64> my current algorithm is currently working with iterate and getting big quickly.
19:48 <help2103980> ok folks, I'll try mixing map and zipWith
19:48 <dmwit> orion: Additionally, the associativity/identity laws come "for free" just by M being an object in a category.
19:49 <help2103980> hope to solve it, thanks for now
19:49 <dmwit> orion: ...as does the first property that arrows are closed under composition, in fact.
19:49 Berra joined
19:49 <dmwit> orion: I don't like this intro. It's very sloppy.
19:49 <orion> dmwit: But isn't an arrow from M -> M just the identity morphism?
19:50 <dmwit> orion: No, there can be many non-identity morphisms with that type.
19:50 <orion> But isn't the arrow originating at M and looping back to M?
19:50 <dmwit> orion: e.g. in the category of sets as objects and functions as arrows, the set {0, 1} has the arrow {(0,1), (1,0)} as a non-identity endomorphism.
19:51 <dmwit> orion: (Or in Haskell notation, this is `Bool` with `not`.)
19:51 <dmwit> ?quickcheck \x -> not x == id x -- no way!
19:51 <lambdabot> Unknown command, try @list
19:51 <dmwit> ?check \x -> not x == id x -- no way!
19:51 <lambdabot> <hint>:1:53: error:
19:51 <lambdabot> parse error (possibly incorrect indentation or mismatched brackets)
19:51 <dmwit> ...huh
19:52 bjz_ joined
19:52 <dmwit> I guess it doesn't like comments.
19:52 <dylukes> undo m = do { cont ← some lenses to get continuation; local (id cont) m }
19:52 <dylukes> Rembane
19:52 <dylukes> in theory very simple.
19:52 carlosdagos joined
19:52 <dylukes> Having a usable stack would be more helpful though.
19:52 <orion> dmwit: Yes, I realize that (not x) is not the same as (id x). But if I drew this pictorally, I would see a dot labeled M and an arrow originating at M and looping back to M.
19:52 <dylukes> Also for a history panel.
19:53 <dmwit> orion: What is "this" in that sentence?
19:53 <dylukes> (I could also then store some descriptive information about the change.)
19:53 <dylukes> (Explicit > Implicit)
19:54 <orion> dmwit: If I drew a picture of the "not" morphism and the "id" morphism on M.
19:54 <Rembane> dylukes: Seems like a working solution.
19:54 <orion> dmwit: Visually, they would be indistinguishable.
19:54 <dmwit> orion: I don't think that's what you would see. I think you would see a dot labeled M and *two* arrows originating at M and looping back to M.
19:54 windsing joined
19:54 cardboard64 joined
19:55 <orion> dmwit: err, yes. There would be two, and the labels would be interchangable.
19:55 <dmwit> One arrow would be labeled `id` and the other arrow would be labeled `not`.
19:55 <dmwit> Why would the labels be interchangeable?
19:55 <orion> Because they both start at M and and at M.
19:55 mkoenig joined
19:55 <dmwit> So what?
19:55 <orion> So the labels are interchangable.
19:55 <dmwit> No.
19:56 <dmwit> Or: what does "interchangeable" mean?
19:56 <orion> It means that if I drew it on a whiteboard, I could erase both "id" and "not", and write "not" where "id" was and "id" where "not" was and still be correct/valid.
19:56 <help2103980> ph88^, may I send you a private message, so I won't flood the main discussion?
19:56 <dmwit> orion: Okay. What do you conclude from that?
19:57 mexisme2 joined
19:57 <orion> dmwit: That without knowing the "implementation details" of the category (that we're talking about Hask), there's nothing more I can say.
19:57 <Welkin> `id` is literally the identity function
19:58 <dmwit> orion: Okay. I admit I'm a bit lost. Do you now understand the text at the link, or is there still a question? If so, what is the question?
19:59 <orion> dmwit: I am trying to grok category theory, and I think I am just verbally spewing thoughts as they enter my head without any filter.
19:59 <orion> So, I don't think there are any more questions at this time. Thank you. :)
20:00 <nshepperd_> orion: but a category isn't just a directed graph, it also has properties like the result of composition of arrows
20:01 <nshepperd_> That lets you distinguish not and id
20:01 <ph88^> help2103980, sure
20:01 <nshepperd_> because not . id = not
20:02 caumeslasal joined
20:02 JuanMiguel joined
20:04 <nshepperd_> I guess you draw things like that as diagrams
20:04 <orion> nshepperd_: Is it true that without knowing the "semantics" of the category involved, it's impossible to come to any useful conclusions about a given diagram?
20:04 <dmwit> Yes, if you drew the diagram orion described, a CT expert would probably be confused because that diagram does not commute. =P
20:04 <nshepperd_> Like a triangle diagram with not on two sides and id on the other
20:04 <centril> Welkin: so I found hscolour (Language.Haskell.HsColour) and pretty-simple (Text.Pretty.Simple) for pretty printing expressions with indentation and colour... any preference ? (anyone else is free to answer)
20:05 <nshepperd_> Or something, i dunno
20:05 <dmwit> orion: I think you have painted yourself into a corner. Probably the answer to that question will be "you are about to define semantics as being the information you need to know to draw conclusions about a given diagram".
20:05 <orion> ha
20:05 <orion> You might be right.
20:07 louispan joined
20:08 barrucadu joined
20:08 barrucadu joined
20:09 <nshepperd_> orion: I'm not sure what that means. A category consists of (1) some objects (2) some arrows, including an identity arrow for each object and (3) an associative composition operator that respects the identities
20:09 caumeslasal joined
20:09 <nshepperd_> The composition properties are an essential part of the category. Not anything extra
20:09 <implementation> does someone know more details about "brkPrefix" and "brkSuffix" in text-icu (haddocks just say "Prefix of the current break.")? what can I assume about their results? how do they differ from brkBreak and how long is the prefix/suffix?
20:09 rodlogic joined
20:09 Goplat joined
20:10 contiver joined
20:10 ijp joined
20:11 adamCS joined
20:12 <dmwit> Have you tried looking at the source?
20:17 knupfer joined
20:18 <knupfer> Are there plans to provide string operations for Symbol?
20:18 eduardm joined
20:18 <dmwit> Let me say that another, less passive-aggressive way (sorry about that). I don't know the answer, and it's possible that nobody who's hanging around does either. It might be time to check the source and try to work it out from first principles.
20:18 jeltsch joined
20:19 <knupfer> ?
20:19 <dmwit> knupfer: That was aimed at implementation, not you. =P
20:19 <dmwit> You just happened to step into the crossfire.
20:20 <knupfer> Ah ok :)
20:20 sssilver joined
20:20 <knupfer> I'm trying to write a parsing lib which defines it's grammar on the typelevel
20:20 coot joined
20:20 <knupfer> so it's inspectable and optimizable at compiletime
20:21 slack1256 joined
20:23 e14 joined
20:25 mpiechotka joined
20:26 <mpiechotka> @pl \(a, b) -> ((flip (,) b) +++ (flip (,) b)) a
20:26 <lambdabot> uncurry (flip (ap ((+++) . flip (,)) (flip (,))))
20:26 <erisco> :t (+++)
20:26 <lambdabot> ArrowChoice a => a b c -> a b' c' -> a (Either b b') (Either c c')
20:28 xaviergmail joined
20:30 takle joined
20:30 augur joined
20:30 SpinTensor joined
20:31 e14 joined
20:33 <orion> dmwit / nshepperd_: If (g . f) != (f . g) does that mean that, by definition, f and g are not isomorphic?
20:33 <orion> Conversely, if (g . f) != (f . g), does that mean that f and g are, always and forever, isomorphic?
20:33 <orion> s/!=/==
20:33 <laudiacay> / 5
20:33 <monochrom> knupfer: While I can feel that type-level something will help, I doubt that it is going to be type-level string. If anything it ought to be type-level tree or something.
20:33 takle joined
20:34 fizbin joined
20:34 eacameron joined
20:34 <ph88^> hi guys, i'm trying to combine 2 functions see line 67 at https://bpaste.net/show/32a57e8e2a6a but i get an error which i don't understand, can someone help me a little bit and give some advice about this ?
20:36 <c_wraith> ph88^, that just is telling you that you haven't enabled either of the extensions that enable ~ constraints
20:36 <dmwit> orion: isomorphism is a statement about objects, not arrows
20:36 cpup joined
20:36 augur joined
20:37 MarioBranco joined
20:37 e14 joined
20:37 <erisco> mpiechotka, uncurry (flip ((+++) <$> flip (,) <*> flip (,)))
20:38 fotonzade joined
20:38 curious_corn joined
20:38 <erisco> I thought uncurry (flip (join (+++) . flip (,))) at first but this is a subtle trap
20:38 <orion> dmwit: Ah.
20:38 <orion> Yes, very true. That resolves it, thanks.
20:40 <mpiechotka> erisco: Thanks
20:42 <erisco> this time @pl was just about there. only needed some name changes
20:42 oisdk joined
20:44 jomg joined
20:45 ph88_ joined
20:45 robkennedy joined
20:46 Discovery joined
20:46 augur joined
20:46 peterbec` joined
20:46 peterbecich joined
20:47 oisdk_ joined
20:48 Sgeo joined
20:50 tromp joined
20:50 Bryte_ joined
20:51 baroncharlus joined
20:54 <ph88_> c_wraith, ah yes you are right, when i try it in ghci it works https://bpaste.net/show/d8ca13d7f50e however the infered type is rather complicated, and i'm not sure what i should put in my source file
20:57 Jesin joined
20:57 leat joined
20:58 a3Dman joined
20:58 doodlehaus joined
20:58 mda1 joined
20:58 SCHAAP137 joined
20:59 Qommand0r joined
20:59 Swizec joined
21:00 e14 joined
21:00 wing22 joined
21:01 verement joined
21:01 robertkennedy joined
21:05 Tuplanolla left
21:07 Deadhand joined
21:07 <wing22> hi, anyone have tried any gui work in haskell
21:07 AfC joined
21:08 <ph88_> hi wing22
21:08 <ph88_> wing22, how would you feel using electron for gui ?
21:08 Tuplanolla joined
21:09 <ph88_> c_wraith, i updated that paste a little bit to make things more clear, i'm trying to find the right type to put in my file but the type expansion confuses me https://bpaste.net/show/fc2411004aaf
21:09 <ph88_> that is the infered type is not enough and i have to put a type signature on that function, but i don't know what it should be
21:09 <wing22> atom electorn ? nay, i'm running away from js
21:09 diegoksp joined
21:10 <ph88_> wing22, any toolkit you have in mind ? or you want to do native OS api ?
21:11 tomphp joined
21:11 <ph88_> wing22, there are a lot of languages that compile to javascript, do you don't have to write JS. For example you can do haskell + electron and purescript .. seems like an excellent combo to me
21:13 <ph88_> wing22, maybe this helps https://wiki.haskell.org/Applications_and_libraries/GUI_libraries
21:13 balor joined
21:14 Scip joined
21:15 <wing22> acutully i have simple gui written in F# and I want to port it
21:15 cardboard64 left
21:16 <ph88_> sounds like a nice project :)
21:17 <ph88_> wing22, just for my own curiosity .. how did you like F# and why are you porting the app ?
21:18 <wing22> f# good, haskell better :) *** as language only ***
21:18 <ph88_> i have to go, be back later
21:18 <wing22> thank you ph88_
21:19 eacameron joined
21:20 <centril> has anyone used the pretty-simple package ? (Text.Pretty.Simple)
21:20 <centril> it's supposed to colourize the stuff, but it is not - at least not in my terminal
21:21 <centril> it says "ANSI escape codes" tho, so it should work
21:22 ph88^ joined
21:26 e14 joined
21:27 <lyxia> centril: I can see colors
21:27 deech joined
21:27 <lyxia> centril: my strings are blue
21:27 shanemikel joined
21:28 <centril> lyxia: weird... hscolour manages to print with colour for me tho
21:28 <centril> using: Language.Haskell.HsColour.TTY
21:29 <centril> lyxia: my terminal is cmd.exe (windows)
21:29 <deech> Hi all, had a question about GHC's garbage collection. By default does GHC only start cleaning up once the heap has reached a certain size or is it always by time?
21:29 <shanemikel> Ryan Trinkle did an amazing job packaging his reflex-platform with Nix. I really wish projects like GHCJS had more folks working on usability points like this...
21:30 xaviergmail joined
21:30 bjz joined
21:30 LuckyRawApe joined
21:30 oisdk joined
21:34 {emptyset} joined
21:35 cpup joined
21:35 meoblast001 joined
21:37 mkoenig joined
21:37 esssing joined
21:37 e14 joined
21:38 shanemikel joined
21:41 vaibhavsagar joined
21:41 Koterpillar joined
21:42 ddellacosta joined
21:42 shanemikel joined
21:42 Bryte joined
21:43 <ddellacosta> I have a feeling someone on here knows the answer to this: where can I go to read about the provenance of this usage of "morally correct?" http://www.cse.chalmers.se/~nad/publications/danielsson-et-al-popl2006.html
21:44 <ddellacosta> I often see this usage in PLT discussions, but I don't have any significant math or philosophy background that would help me effectively understand this usage
21:44 <davean> ddellacosta: fast and lose reasoning, its a paper
21:45 <geekosaur> deech, both. More precisely, a gc is done during the next allocation if the heap (or nursery, for minor gc) is overfull, or if the timer has gone off
21:45 <davean> ddellacosta: oh, you already see that paper
21:45 <davean> ddellacosta: "morally" isn't a technical thing persay
21:45 <ddellacosta> davean: are you saying the paper I linked to is exactly the origin of the usage of "morally correct" in PLT discussions?
21:45 <geekosaur> ddellacosta, I think the whole title is deliberately informal and a bit over the top
21:46 <ddellacosta> geekosaur, davean, that's helpful
21:46 <ddellacosta> I thought that perhaps there was a precise meaning when used in a compsci/math/type theory context that I was missing entirely
21:46 <geekosaur> and it wouldn't surprise me if that paper indeed introduced the usage. Not all mathematics or CS is stuffy academics
21:46 <ddellacosta> oh sure, it's more just that I'm ignorant enough that I don't know when I've encountered an informal term or something in the lexicon
21:46 <geekosaur> (cf. "generalized abstract nonsense" for CT)
21:46 <ddellacosta> right, gotcha
21:47 Destol joined
21:47 <davean> geekosaur: Sometimes we call generalized abstract nonsense catagory theory but thats just when we get tired of such a long name
21:48 <geekosaur> :)
21:48 <ddellacosta> ha
21:49 <davean> ddellacosta: If you read that paper, I think you'll get a sense of the usage though
21:49 <ddellacosta> davean: I'll give it a shot! Thanks so much to you and geekosaur for the help, that clarified things a lot
21:49 Unhammer joined
21:50 <Phyx-> centril: I assume you're on Windows 10 then? or have something like ANSICON installed?
21:50 infinity0 joined
21:50 eacameron joined
21:50 <deech> geekosaur: So should I worry that my app's RAM usage went from 11 -> 40 MB over the course of 3-4 minutes of usage?
21:51 JeanCarloMachado joined
21:51 <geekosaur> deech, that suggests to me you are having too much stuff held active, not a problem with gc but a problem with letting stuff be eligible for gc
21:51 knupfer` joined
21:51 <geekosaur> excessive sharing can cause itg
21:52 <davean> deech: link to your app's code?
21:52 mkoenig joined
21:52 hiratara joined
21:52 <c_wraith> It's also worth noting whether the usage keeps growing. It's possible that there's some shared structure that isn't fully evaluated at first, but does have a finite maximum size
21:54 Sgeo joined
21:54 <deech> davean: It's https://github.com/deech/fltkhs-fluid-demos/blob/master/src/Tree.fl which gets pre-processed into Haskell. It's not ideal for reproducing since it also uses a C++ library.
21:54 canadiangregster joined
21:55 zero_byte joined
21:55 <deech> geekosaur: Do you mean there are too many object in scope?
21:55 oisdk joined
21:55 <c_wraith> deech: well, held by (potentially-unevaluated) objects in scope
21:55 <geekosaur> ^
21:56 <* geekosaur> was writing that but c_wraith got there first...
21:56 <c_wraith> I got there first despite airplane lag? :)
21:56 <davean> deech: I was hoping it was small and Haskelly enough I could review its sharing and strictness and other properties efficiently, but I see it is not :)
21:57 ds joined
21:57 <* geekosaur> is trying to multitask
21:57 <geekosaur> being short on sleep, this is a bit slower than usual
21:58 dawehner joined
21:58 <c_wraith> deech: if there's FFI involved, you could also have a real, old-fashioned memory leak in the allocations it does. Or on the native side.
21:58 oisdk joined
21:58 carlosdagos joined
21:58 marmalod1 joined
21:59 <deech> davean: Thanks for offering, though!
22:01 ziocroc joined
22:02 raynold joined
22:03 Bryte joined
22:05 matt_ joined
22:05 CaptJakk joined
22:06 maerwald joined
22:06 marr joined
22:09 louispan joined
22:10 ragepandemic joined
22:10 dylukes joined
22:13 xkapastel joined
22:15 <centril> Phyx-: yes, win10
22:16 vaibhavsagar joined
22:18 carlomagno joined
22:18 meba joined
22:21 infinity0 joined
22:24 Qommand0r joined
22:25 Rizy joined
22:29 a3Dman joined
22:30 ebzzry joined
22:31 Sgeo joined
22:31 hiratara joined
22:35 raycoll joined
22:37 mson joined
22:37 louispan joined
22:38 MP2E joined
22:45 marcopullo joined
22:46 athan joined
22:50 tromp joined
22:52 eacameron joined
22:56 hpd joined
22:56 hpd left
22:57 farrioth joined
22:57 indi_ joined
23:01 Welkin joined
23:02 doodlehaus joined
23:03 skeuomorf joined
23:04 gpbaran joined
23:06 fizbin joined
23:06 Reshi joined
23:06 shubhaml joined
23:06 systadmin joined
23:07 watabou joined
23:09 Rizy joined
23:12 louispan joined
23:12 acidjnk joined
23:13 <orion> Are all co-products algebraic sum types?
23:13 a3Dman joined
23:14 <Koterpillar> Up to isomorphism
23:19 <orion> Great, thanks.
23:19 JeanCarloMachado joined
23:20 juicyasf joined
23:20 a3f_ joined
23:20 AX3L joined
23:21 lambda-11235 joined
23:21 a3f_ joined
23:21 Guest71307 joined
23:22 juicyasf joined
23:24 Lord_of_Life joined
23:24 Lord_of_Life joined
23:24 cschneid_ joined
23:27 knupfer` left
23:27 refold joined
23:28 juicyasf joined
23:30 gpbaran joined
23:31 Hoier joined
23:32 HoierM joined
23:33 systadmin joined
23:33 benl23 joined
23:35 dan_f joined
23:36 {emptyset} joined
23:36 louispan joined
23:38 ebzzry joined
23:39 kav joined
23:42 a3Dman joined
23:45 canadiangregster left
23:46 gpbaran joined
23:48 ARR joined
23:52 robkennedy joined
23:54 gcross joined
23:55 vydd joined
23:55 vydd joined
23:55 AAA_ joined
23:56 clmg joined
23:56 peterbecich joined
23:56 <clmg> Is there any way to ignore a maybe value with a lens?
23:56 laudiacay left
23:56 <clmg> I want to say `if a^.b^.c then foo`
23:56 <clmg> but a b and c are all maybes
23:57 <clmg> I want the case in which they are Just
23:57 <clmg> otherwise do nothing
23:57 <lyxia> what is foo
23:57 <clmg> operation in c
23:57 <clmg>
23:57 <clmg> on*
23:58 <benzrf> clmg: perhaps you want _Just
23:58 <dolio> b and c are Maybe (Lens ...)?
23:58 <clmg> but I'd need so many nester case statements case a of Just ... case b of Just...
23:59 fizbin joined
23:59 <benzrf> what are the types precisely
23:59 xaviergmail joined
23:59 <clmg> custom data types