Search Haskell Channel Logs

Monday, February 6, 2017

#haskell channel featuring opqdonut, lyxia, Darwin226, reactormonk, BernhardPosselt, hpc, and 6 others.

lyxia 2017-02-06 00:45:23
Isn't applicative do also compatible with functors
dramforever 2017-02-06 00:45:55
They do?
lyxia 2017-02-06 00:45:57
do { x <- y ; return (f y) } gets desugared to fmap f y
dramforever 2017-02-06 00:46:49
ok
dramforever 2017-02-06 00:47:06
that's pretty awesome
dramforever 2017-02-06 00:48:57
All heil GHC!!
Darwin226 2017-02-06 00:58:40
Hey guys. How do I write instances for custom kinds? Say I have a datatype `data K = A | B`. How do I write an instance for the `K` KIND, not the type? `instance C 'K` doesn't work saying K is not a data constructor, but `instance C K`
Darwin226 2017-02-06 00:58:46
doesn't mean the same thing
Darwin226 2017-02-06 00:59:50
Hmmm, or does it?
lyxia 2017-02-06 01:00:19
DataKinds makes the type K also a kind.
lyxia 2017-02-06 01:00:56
So, it's the same.
merijn 2017-02-06 01:01:19
Darwin226: You can use a tick to incidate you mean the lifted type
merijn 2017-02-06 01:01:27
Darwin226: 'Foo for the DataKinds version
Darwin226 2017-02-06 01:02:11
merijn: Ok, so does the distinction not make sense for the higher levels?
merijn 2017-02-06 01:02:35
Darwin226: Can you lpaste a minimal example?
Darwin226 2017-02-06 01:02:51
Sure
Darwin226 2017-02-06 01:06:12
merijn: http://lpaste.net/352132
reactormonk 2017-02-06 01:07:57
How strong is the gitter movement in haskell? In scala, everyone's over there.
merijn 2017-02-06 01:08:47
I don't even know what gitter is, but since it has 'git' in the name, I already don't like it :)
merijn 2017-02-06 01:09:39
Darwin226: What's the error? If any?
Darwin226 2017-02-06 01:09:52
There is none. This is probably what bothers me
Darwin226 2017-02-06 01:10:12
It seems like "it worked out" when it probably shouldn't have
merijn 2017-02-06 01:10:17
Darwin226: Oh, actually I see the problem
merijn 2017-02-06 01:10:36
Darwin226: Now that I think about it, the entire premiss doesn't really make sense
merijn 2017-02-06 01:10:45
Darwin226: It's just using 'K' the type
merijn 2017-02-06 01:10:54
You can't instantiate classes for kinds
merijn 2017-02-06 01:11:01
Because classes are already kind level in GHC
Darwin226 2017-02-06 01:11:09
I don't think that's true anymore with TypeInType
Darwin226 2017-02-06 01:11:25
and indeed without the second instance the first one doesn't compile
Darwin226 2017-02-06 01:11:35
saying there's a missing KindConstraint instance for K
merijn 2017-02-06 01:11:36
oh...I'm not touching a mix of TypeInType + DataKinds if things are confusing :)
Darwin226 2017-02-06 01:13:14
I think I'll just hope that this works
ongy 2017-02-06 01:16:55
most people here use haskell rather to not have to hope
BernhardPosselt 2017-02-06 01:21:25
in java you usually do layered design where you pass in the lower layers through the constructor
BernhardPosselt 2017-02-06 01:21:30
how does this translate to haskell?
BernhardPosselt 2017-02-06 01:21:52
are my layers functions and DI partial application?
BernhardPosselt 2017-02-06 01:23:48
e.g. you've got a function that returns a customer from a database, e.g. getCustomerById connection id = …
BernhardPosselt 2017-02-06 01:24:12
then i'd partially apply the function so it matches getCustomerById id = …
merijn 2017-02-06 01:24:42
BernhardPosselt: tbh, I've looked up what dependency injection like 10 times by now, and every time I do it always seems rather trivial and then I end up forgetting what the entire point was
BernhardPosselt 2017-02-06 01:25:18
merijn: its basically: pass in stuff that you need instead of using a global/singleton
merijn 2017-02-06 01:25:24
BernhardPosselt: As for the partial application thing, that sounds a rather common approach, yes
dramforever 2017-02-06 01:25:26
BernhardPosselt: That's good enough I think
hpc 2017-02-06 01:26:17
so... taking something as a parameter is considered rare and noteworthy enough in java that it got the name "dependency injection"?
merijn 2017-02-06 01:26:27
hpc: Basically
BernhardPosselt 2017-02-06 01:26:34
hpc: not only limited to java
cocreature 2017-02-06 01:26:52
hpc: "adding a parameter" doesn't sound so clever
Darwin226 2017-02-06 01:26:57
BernhardPosselt: Haskell lets you have constraints on the actual context in which your function is running so you can actually avoid the whole parameter passing thing and let it happen automatically
BernhardPosselt 2017-02-06 01:27:03
hpc: the global/static/singleton cancer is everywhere
dramforever 2017-02-06 01:27:04
parameters are very underappreciated
dramforever 2017-02-06 01:27:13
in imperative languages, that is
merijn 2017-02-06 01:27:29
BernhardPosselt: There's a couple of different ways to deal with this sorta thing, but generally 80% of them tend to be solved by "parameter to a function", which after a while makes it seems so needlessly complex in other languages
merijn 2017-02-06 01:28:06
BernhardPosselt: The bonus of (most) things being immutable by default, the entire point of global/static/singleton mostly disappears :p
BernhardPosselt 2017-02-06 01:28:19
merijn: right
dramforever 2017-02-06 01:28:26
global constants are not like they matter
dramforever 2017-02-06 01:28:41
*That's* something I really like about immutability
BernhardPosselt 2017-02-06 01:29:36
so typeclasses kinda seem similar to interfaces
merijn 2017-02-06 01:29:56
Yes and no
BernhardPosselt 2017-02-06 01:30:06
instead of creating a getCustomerById function, would i create a CustomerRepository typeclass which defines the single functions?
merijn 2017-02-06 01:30:10
There are some things interfaces can't express
merijn 2017-02-06 01:30:41
BernhardPosselt: Generally not, I would usually just stick to a function that takes an extra argument
liste 2017-02-06 01:31:00
BernhardPosselt: interfaces specify objects, type classes specify types
liste 2017-02-06 01:31:19
BernhardPosselt: that's the big difference
hpc 2017-02-06 01:31:34
type classes are largely more like operator overloading
hpc 2017-02-06 01:31:47
and you don't get the polymorphism you might expect out of them
liste 2017-02-06 01:31:50
^ that, both are ad-hoc polymorphism
liste 2017-02-06 01:31:59
operator overloading and type classes
merijn 2017-02-06 01:32:06
Some things interfaces generally can't do is: Enforce "sameness" on multiple arguments, consider "(==) :: Eq a => a -> a -> Bool" <- this requires both arguments to == to be the same type
hpc 2017-02-06 01:32:09
for instance in java, you could have an array of type SomeInterface[]
hpc 2017-02-06 01:32:15
and a bunch of things that implement that interface
hpc 2017-02-06 01:32:22
now you have a relatively heterogenous array
hpc 2017-02-06 01:32:35
in haskell, SomeTypeClass a => [a] is a homogenous linked list
merijn 2017-02-06 01:32:38
Whereass if you'd have like a Comparable interfaces in Java with "bool compare(Comparable c1, Comparable c2);" you have no way to guarantee c1 and c2 are the same type
Darwin226 2017-02-06 01:33:09
I don't know how familiar people here actually are with modern OOP but these days all of these things are perfectly expressable with interfaces
merijn 2017-02-06 01:33:31
Darwin226: You could do a reasonable Comparable with a generic based interface, I suppose
dramforever 2017-02-06 01:33:37
You mean generics?
Darwin226 2017-02-06 01:33:45
yes, and it's exactly how it's done
hpc 2017-02-06 01:33:53
fun fact, java generics were designed by one of the original haskell designers
merijn 2017-02-06 01:34:05
Darwin226: Generics can't do all of the things typeclasses can, though
Darwin226 2017-02-06 01:34:12
what you can't do is define instances/implementations on existing types that you can't change
Darwin226 2017-02-06 01:34:20
and you can't do higher-kinded stuff in most OOP languages
Darwin226 2017-02-06 01:34:58
Oh, and you can't do conditional implementation that depends on some other implementation existing
hpc 2017-02-06 01:35:04
you also still don't get type safety for your compare method
Darwin226 2017-02-06 01:35:10
You do
hpc 2017-02-06 01:35:18
bool compare(Comparable c1, Comparable c2)
hpc 2017-02-06 01:35:46
but if you do compare((Object)(new Foo()), (Object)(new Bar())), how does it compare them?
dramforever 2017-02-06 01:35:47
something like compare (T c1, T c2)
dramforever 2017-02-06 01:36:01
I think Java can do this
hpc 2017-02-06 01:36:03
they're the same type, with T = Object
dramforever 2017-02-06 01:36:05
now
Darwin226 2017-02-06 01:36:07
the type T implements Comparable interface
hpc 2017-02-06 01:36:16
but they still have different method implementations
Darwin226 2017-02-06 01:36:19
which specifies something like bool Compare(T other)
Darwin226 2017-02-06 01:36:37
it's completely typesafe
dramforever 2017-02-06 01:36:42
I think we're already off the track here
Ford_Prefect 2017-02-06 01:36:46
Hi folks. I'm trying to use Persistent here, and I've got insert working fine. I can't figure out what to do with selectList, though -- do something to explicitly go from [Entity record] to [MyDataStructure]?
Ford_Prefect 2017-02-06 01:37:09
Or am I thinking about this all wrong? :)
Darwin226 2017-02-06 01:37:29
Also this attitude with saying DI is a "fancy name for extra parameters" is really not healthy
merijn 2017-02-06 01:37:35
Ford_Prefect: Entity is just a tuple of the ID of your record and the actual record
BernhardPosselt 2017-02-06 01:37:54
so tl;dr you dont use type classes to create a collection of functions but to make stuff fit into a generic function
Darwin226 2017-02-06 01:38:09
DI is a way of structuring code. Extra parameters are just the most approachable way of doing it
merijn 2017-02-06 01:38:27
Ford_Prefect: See: http://www.yesodweb.com/book/persistent#persistent_fetching_by_unique_constraint
Darwin226 2017-02-06 01:38:28
not to mention it's probably one of the OO patterns that works out the best in Haskell
dramforever 2017-02-06 01:39:31
BernhardPosselt: Yes, TCs are for types, as the name says
dramforever 2017-02-06 01:39:49
TIL DC is that easy
dramforever 2017-02-06 01:40:04
I meant DI
Ford_Prefect 2017-02-06 01:40:31
merijn: awesome, thanks!
hpc 2017-02-06 01:40:37
BernhardPosselt: a lot of type classes come with laws that all instances need to follow, too
opqdonut 2017-02-06 01:40:41
Darwin226: how does DI work in haskell?
dramforever 2017-02-06 01:40:52
by passing parameters
dramforever 2017-02-06 01:41:11
' DI is a way of structuring code. *Extra parameters* are just the most approachable way of doing it' (emphasis added)
opqdonut 2017-02-06 01:41:27
right, pureness enforces DI in that sense?
hpc 2017-02-06 01:41:32
BernhardPosselt: Monoid has mempty and mappend, with the laws that (mempty `mappend` x) = x = (x `mappend` mempty), and (x `mappend` y) `mappend` z = x `mappend` (y `mappend` z)
hpc 2017-02-06 01:41:51
(or in other words, mappend is associative and mempty is both a right and left identity of mappend)
hpc 2017-02-06 01:42:07
and that's something that shows up in a lot of places that we would like to be able to think about in a common way
Darwin226 2017-02-06 01:42:27
opqdonut: My favorite way is MTL classes or effects. You declare what your function wants to do and the caller decides how it's done.
hpc 2017-02-06 01:42:30
but so many things have those properties and we don't want to miss any, that we make it a type class so it's "open"
Darwin226 2017-02-06 01:42:51
opqdonut: passing parameters is the trivial case of MTL classes where the classes is MonadReader
liste 2017-02-06 01:43:03
BernhardPosselt: a record of functions is more analogous to Java's interface
dramforever 2017-02-06 01:43:04
Actually, dare I say, typeclasses are generally suitable for the more 'mathematical' structures
merijn 2017-02-06 01:43:08
Darwin226: Until you need multiple of those ;)
dramforever 2017-02-06 01:43:18
if a structure isn't general enough it's probably not worth a typeclass
hpc 2017-02-06 01:43:21
so to some extent it's a way to automatically build an interface from a few primitives
hpc 2017-02-06 01:43:33
(an interface as in "API", not as in some language keyword)
dramforever 2017-02-06 01:43:39
For example, Applicative is totally amazing
opqdonut 2017-02-06 01:44:03
Darwin226: hmm right, I haven't thought of that as DI but I guess it is
BernhardPosselt 2017-02-06 01:44:05
liste: good point
BernhardPosselt 2017-02-06 01:44:09
havent thought of that :)
hpc 2017-02-06 01:44:32
when you write a new instance of Num, you get the operations you defined like (+) and fromInteger
hpc 2017-02-06 01:44:38
but also sum, which you didn't write
hpc 2017-02-06 01:44:47
and you get the Sum and Product newtypes which both have Monoid instances
liste 2017-02-06 01:45:05
BernhardPosselt: eg. data Drawable = MkDrawable { draw :: DC -> IO (); bounds :: (Int, Int, Int, Int) }
hpc 2017-02-06 01:45:08
> let xs = map Sum [1, 2, 3, 4, 5] in mconcat xs