Search Haskell Channel Logs

Tuesday, March 7, 2017

#haskell channel featuring Freundlich, Akii, Maxdamantus, Adeon, geekosaur, dramforever,

geekosaur 2017-03-06 22:55:47
that's not BangPatterns though, it's core Haskell
Akii 2017-03-06 22:56:57
not anymore maybe https://downloads.haskell.org/~ghc/7.8.4/docs/html/users_guide/bang-patterns.html
geekosaur 2017-03-06 22:57:08
but in any case it means any time a value is constructed, that field's value will have seq applied to it so it has been evaluated to the first constructor. (this does not guarantee full strictness, except for "atomic" types like Int)
merijn 2017-03-06 22:57:25
Akii: Hasn't been an extension in years, if ever
geekosaur 2017-03-06 22:57:25
no, BangPattgerns is for use in patterns. use in data constructors is Haskell98
merijn 2017-03-06 22:57:34
Akii: bang patterns is about *patterns*, not constructors
merijn 2017-03-06 22:57:37
Hence, the name
Akii 2017-03-06 22:57:50
merijn: got confused about -XBangPatterns; I only know that from lang extensions
Akii 2017-03-06 22:59:22
so, I also see this bang pattern being used occasionally; when should I use it?
geekosaur 2017-03-06 23:00:04
most common use is when you are deconstructing/pattern matching with let; case and top-level pattern bindings are strict by default
Akii 2017-03-06 23:01:49
geekosaur: and with data constructors?
geekosaur 2017-03-06 23:01:52
hm, either I am misremembering that or it's a related extension
geekosaur 2017-03-06 23:02:23
data constructors are a different issue, any time you build a value with that constructor it will be lazy unless the declaration included a bang on the type
geekosaur 2017-03-06 23:02:59
this is not related to pattern matching: even if you match a value of that type, it's something that already exists so no constructor behavior would be applied to it
geekosaur 2017-03-06 23:03:50
(remember type and data constructors are in separate namespaces)
Akii 2017-03-06 23:04:09
and with `data Foo = Foo !Int !String` it would evaluate directly
Akii 2017-03-06 23:04:17
(yes, I know; just typo :D)
Akii 2017-03-06 23:04:38
that's very interesting
Akii 2017-03-06 23:05:14
for me that means: if I produce a lot or if I definitely need those values when constructing a data type, I use strict evaluation
geekosaur 2017-03-06 23:05:27
it depends on usage
geekosaur 2017-03-06 23:05:53
if it is often part of a computation that would otherwise end up being discarded much of the time, strictness will cause slowdowns
Akii 2017-03-06 23:06:49
I don't understant
Akii 2017-03-06 23:06:55
understand* xD
Akii 2017-03-06 23:07:10
what's the slowdown; discarding the thunk vs discarding the value?
Akii 2017-03-06 23:07:28
ah yes sorry
Akii 2017-03-06 23:07:37
"strictness will cause slowdowns"
Akii 2017-03-06 23:07:41
somehow read laziness >.<
Akii 2017-03-06 23:07:45
of course ^^
geekosaur 2017-03-06 23:07:55
the thunk ends up part of a value you never reach because something else is doing a take 3 that never reaches it, or something
geekosaur 2017-03-06 23:08:04
so you forced a value to no point
Akii 2017-03-06 23:08:37
generating thunks just uses up more memory then?
geekosaur 2017-03-06 23:09:12
thunks are usually cheap, it's forcing values that is expensive. but it depends on what you do with them, as usual
Akii 2017-03-06 23:09:28
well I had one case where I ended up with 4 GB of thunks
geekosaur 2017-03-06 23:09:32
which is why you really need to profile and not just sprinkle bangs on stuff liek salt
Akii 2017-03-06 23:09:34
that was fun
Akii 2017-03-06 23:09:43
like salt bae xD
Akii 2017-03-06 23:10:01
okay, thanks!
geekosaur 2017-03-06 23:10:06
reasoning about where laziness helps and where it hurts is *hard*
geekosaur 2017-03-06 23:11:07
thunks can consume memory if they stack up in the pattern match stack. heap allocations can consume memory as well. (the foldr/foldl issue)
geekosaur 2017-03-06 23:11:29
one is from too much laziness, the other from being too strict
geekosaur 2017-03-06 23:13:17
and one of the strengths of haskell is laziness lets you specify work that won't be done if it's not needed (e.g. infinite lists) if that's the natural way to express something; strictness will hurt you in this case
geekosaur 2017-03-06 23:13:59
go the "must strict everything!" route and you end up writing Haskell-flavored C instead of Haskell
geekosaur 2017-03-06 23:14:40
because common Haskell idioms and even common Haskell library functions will choke if you are too strict
Adeon 2017-03-06 23:14:57
I also find non-strict semantics a readability benefit
Akii 2017-03-06 23:14:59
other than the one issue (where I expected nothing else) I never had any problems with laziness so far
Akii 2017-03-06 23:15:12
but good to keep in mind; some day I'll run into an issue :D
Adeon 2017-03-06 23:15:12
sometimes I can write expensive computations in a function with confidence none of that will be computed if it turns out they don't need to be
Aku 2017-03-06 23:29:28
Can anybody tell me the difference between newtype Parser a = Parser (String -> [(a,String)]) and type Parser a = String -> [(a,String)] ?
ski 2017-03-06 23:30:02
the former declares a new data type. the latter merely gives a synonym to an existing type
ski 2017-03-06 23:30:56
the former could be made an instance of type classes like `Functor',`Applicative',`Monad'. the latter couldn't
Aku 2017-03-06 23:31:01
To declare a new data type we usually write data Colour = Red | Green
ski 2017-03-06 23:31:28
yes
Aku 2017-03-06 23:31:30
What's the difference?
Aku 2017-03-06 23:31:37
ski: ?
ski 2017-03-06 23:31:47
`newtype' is a special case of `data', that's handled slightly differently
dramforever 2017-03-06 23:31:52
Aku: newtype only makes a new type not new data
Aku 2017-03-06 23:32:06
dramforever: okay
dramforever 2017-03-06 23:32:08
It's best thought as a compile-time wrapper of another type
ski 2017-03-06 23:32:22
`newtype' is like `type' in that you can only "wrap" one type. also no multiple data constructors
dramforever 2017-03-06 23:32:26
compile-time only
ski 2017-03-06 23:32:55
but it's like `data' in that you have an explicit data constructor, to construct and deconstruct (pattern-match)
Aku 2017-03-06 23:32:56
ohhkay...
Aku 2017-03-06 23:33:06
ya right
ski 2017-03-06 23:33:22
since it's a new type, the "implementation/representation type" and the new type are considered distinct
Aku 2017-03-06 23:33:59
ohhkay
ski 2017-03-06 23:34:08
one can think of the data constructor of a `newtype' as only existing at compile-time, while at run-time a value of the representation type is passed around directly
Maxdamantus 2017-03-06 23:34:10
The only reason it's not just `data` afaik is its special handling of deconstruction.
Aku 2017-03-06 23:34:11
Thanks
Maxdamantus 2017-03-06 23:34:35
(that is, not just a special case of `data`)
ski 2017-03-06 23:34:44
this means that there's no difference between `Parser undefined' and `undefined' (there would be a difference with `data')
Maxdamantus 2017-03-06 23:34:59
Yeah, that.
ski 2017-03-06 23:35:22
also, matching on the pattern `Parser f' will not demand/force any evaluation
Aku 2017-03-06 23:35:42
hm...
ski 2017-03-06 23:36:10
you can probably ignore these finer points for now
Aku 2017-03-06 23:36:37
ya looks like, I need to read more!
osa1 2017-03-06 23:38:25
*sigh* I sometimes think typeclasses like ToJSON, FromField etc. are actually an anti-pattern. it's especially annoying when only typeclass versions of combinators are provided (e.g. (.:))
osa1 2017-03-06 23:38:51
most of the types don't have a canonical JSON, CSV field etc. representation
merijn 2017-03-06 23:39:35
I really hate that people decided JSON was a reasonable format for serialising shit
Akii 2017-03-06 23:39:50
what's wrong with ToJSON?
merijn 2017-03-06 23:39:53
You can't even reliably store an integer in JSON unless you store it as a string, for christ's sake
merijn 2017-03-06 23:40:04
Akii: You mean "what's wrong with JSON?"
osa1 2017-03-06 23:40:07
Akii: like I said, there most types don't have canonical JSON representation
osa1 2017-03-06 23:40:23
but a type can have one instance of a typeclass
merijn 2017-03-06 23:40:24
I'm sure ToJSON is perfectly reasonable, if you are a priori okay with the idiocy that is JSON
osa1 2017-03-06 23:41:04
merijn: is it? I can implement many JSON representations of a type
Akii 2017-03-06 23:41:32
well Aeson does offer a data type representing JSON
osa1 2017-03-06 23:41:52
Akii: like I said, combinators like (.:) only have typeclass version. I can't provide a parser to (.:)
Freundlich 2017-03-06 23:42:00
osa1: But that's the case for most type classes anyway. Sometimes it's also quite annoying (like what should a monoid of natural numbers be?).
osa1 2017-03-06 23:42:01
so I have to implement a newtype
osa1 2017-03-06 23:42:07
Freundlich: agreed
osa1 2017-03-06 23:42:18
IMHO typeclasses should be used less, not more
ski 2017-03-06 23:42:51
"combinators like (.:) only have typeclass version" ?
osa1 2017-03-06 23:43:30
ski: `(.:) :: FromField a => NamedRecord -> ByteString -> Parser a` I need a version of this function that takes a `fromField` function
osa1 2017-03-06 23:43:57
it's from cassava but similar functions exist in aeson too
Akii 2017-03-06 23:44:00
this? https://hackage.haskell.org/package/aeson-1.1.0.0/docs/Data-Aeson.html#v:.:
ski 2017-03-06 23:44:07
(as opposed to `(.:) :: (c0 -> c1) -> (a -> b -> c0) -> (a -> b -> c1)')
Akii 2017-03-06 23:44:34
this would allow you to write a parser for Value though, which is instance of FromJSON
Akii 2017-03-06 23:44:48
-would +does