Home freenode/#haskell: Logs Calendar

Logs: freenode/#haskell

←Prev  Next→ 502,152 events total
2020-11-06 22:18:01 <cohn> ski: oh!!! I see exactly what you did above. The pattern (MkFoo n s:foos) matches the head of the list, then assigns the tail to "foos"
2020-11-06 22:18:01 Stanley00 joins (~stanley00@unaffiliated/stanley00)
2020-11-06 22:18:08 <cohn> man, I didn't know you could do that
2020-11-06 22:19:42 <cohn> ok, that worked perfectly. Thanks so much!
2020-11-06 22:20:43 <cohn> that makes me question a lot of other code I wrote that I could probably simplify... lol
2020-11-06 22:21:40 × o1lo01ol1o quits (~o1lo01ol1@46.50.92.11) (Remote host closed the connection)
2020-11-06 22:22:22 <ski> cohn : not "assigns", but "binds". but, yes. you can nest patterns inside each other
2020-11-06 22:22:28 × Stanley00 quits (~stanley00@unaffiliated/stanley00) (Ping timeout: 246 seconds)
2020-11-06 22:22:53 _deepfire joins (~user@80.92.100.69)
2020-11-06 22:23:08 × ensyde quits (~ensyde@99-185-235-117.lightspeed.chrlnc.sbcglobal.net) (Ping timeout: 260 seconds)
2020-11-06 22:23:10 <cohn> wow, that's *really* powerful.
2020-11-06 22:23:17 <cohn> not sure why I never saw that before
2020-11-06 22:23:18 <ski> (assignment usually implies overwriting the current value in a location with some (possibly) different value. there is no overwriting here)
2020-11-06 22:23:23 cohn shrugs
2020-11-06 22:23:43 <ski> if you had had `data Foo = SimpleFoo String | ComplexFoo Int String', then you could have done
2020-11-06 22:23:52 <ski> processFoos :: [Foo] -> ...
2020-11-06 22:24:12 <ski> processFoos [ ] = ...
2020-11-06 22:24:39 × pfurla quits (~pfurla@ool-182ed2e2.dyn.optonline.net) (Ping timeout: 256 seconds)
2020-11-06 22:24:52 <ski> processFoos (SimpleFoo s:foos) = ..s..(processFoos foos)..
2020-11-06 22:24:53 thir joins (~thir@p200300f27f0b7e00f4e9381c2bf90854.dip0.t-ipconnect.de)
2020-11-06 22:25:03 <ski> processFoos (ComplexFoo n s:foos) = ..n..s..(processFoos foos)..
2020-11-06 22:25:28 <ski> so, two non-empty list cases, depending on whether the current/first element is simple or complex
2020-11-06 22:25:48 <cohn> ya, that makes sense. really cool stuff
2020-11-06 22:25:49 × ddellaco1 quits (dd@gateway/vpn/mullvad/ddellacosta) (Read error: Connection reset by peer)
2020-11-06 22:26:37 <ski> this is the kind of thing that makes pattern-matching a breeze to work with, as contrasted with a gnarly maze of nested `if'-`then'-`else's (and possibly also `let'-`in's)
2020-11-06 22:26:47 <cohn> exactly!
2020-11-06 22:26:58 <cohn> ditto for the `case` statement
2020-11-06 22:27:06 jedws joins (~jedws@101.184.150.81)
2020-11-06 22:27:11 <ski> yea, but you can also nest patterns with `case'
2020-11-06 22:27:12 o1lo01ol1o joins (~o1lo01ol1@46.50.92.11)
2020-11-06 22:27:24 <ski> processFoos foos0 = case foos0 of
2020-11-06 22:27:32 <ski> [ ] -> ...
2020-11-06 22:27:45 <ski> SimpleFoo s : foos -> ..s..(processFoos foos)..
2020-11-06 22:27:47 pfurla joins (~pfurla@129.15.195.173.client.static.strong-in52.as13926.net)
2020-11-06 22:27:54 <ski> ComplexFoo n s : foos -> ..n..s..(processFoos foos)..
2020-11-06 22:28:00 ensyde joins (~ensyde@99-185-235-117.lightspeed.chrlnc.sbcglobal.net)
2020-11-06 22:28:25 <cohn> that does come in handy
2020-11-06 22:28:41 <ski> (and that `case' could be nested inside some other expression, if you wanted to. and you could have some other expression (other scrutinee) between the `case' and the `of', than just the direct formal parameter `foos0')
2020-11-06 22:29:25 × thir quits (~thir@p200300f27f0b7e00f4e9381c2bf90854.dip0.t-ipconnect.de) (Ping timeout: 244 seconds)
2020-11-06 22:29:27 dbmikus__ joins (~dbmikus@cpe-76-167-86-219.natsow.res.rr.com)
2020-11-06 22:30:00 <cohn> oh nice! that's good to know
2020-11-06 22:30:27 <cohn> fwiw, I'm coming from a Python world so having to get used to types plus FP patterns like this.
2020-11-06 22:30:40 <cohn> sorry if I sometimes ask dumb/obvious questions.
2020-11-06 22:30:42 <cohn> :D
2020-11-06 22:31:13 <ski> algebraic data types (also called sum types, variant types, discriminated/disjoint union types, variant record types), with pattern-matching, are really great
2020-11-06 22:31:23 × Tario quits (~Tario@201.192.165.173) (Read error: Connection reset by peer)
2020-11-06 22:31:24 <ski> no worry :)
2020-11-06 22:32:37 <ski> it's too bad that only few languages supports them. imho, you really need both them, and record types (aka product types, object types, "class types"). sometimes one is more appropriate, sometimes the other. it depends on what you're doing
2020-11-06 22:32:59 <ski> (in a formal sense, they are "duals" of each other. "opposites" in a sense)
2020-11-06 22:33:02 <cohn> ya
2020-11-06 22:33:18 <cohn> duals... man that brings back memories of linear programming
2020-11-06 22:33:24 × ensyde quits (~ensyde@99-185-235-117.lightspeed.chrlnc.sbcglobal.net) (Ping timeout: 272 seconds)
2020-11-06 22:33:34 <cohn> or maybe nightmares... ; )
2020-11-06 22:33:39 <ski> (but i've heard rumors that more languages will be gaining them. e.g. C#, and hopefully more)
2020-11-06 22:33:57 × conal quits (~conal@198.8.81.71) (Quit: Computer has gone to sleep.)
2020-11-06 22:34:37 × nbloomf quits (~nbloomf@2600:1700:ad14:3020:2d48:c414:1e60:fe62) (Quit: My MacBook has gone to sleep. ZZZzzz…)
2020-11-06 22:34:38 <ski> heh, okay :)
2020-11-06 22:36:38 <ski> (unfortunately, it's common in OO (which is all about record/product/object types), to claim that `switch' is bad. (pattern-matching can be viewed as `switch' on steroids.) it's not bad, it's just that sometimes product types are more appropriate. and sometimes, sum types are more appropriate)
2020-11-06 22:36:51 rprije joins (~rprije@124.148.131.132)
2020-11-06 22:37:43 conal joins (~conal@198.8.81.71)
2020-11-06 22:37:47 <cohn> agreed.
2020-11-06 22:38:12 ensyde joins (~ensyde@99-185-235-117.lightspeed.chrlnc.sbcglobal.net)
2020-11-06 22:38:29 × o1lo01ol1o quits (~o1lo01ol1@46.50.92.11) (Remote host closed the connection)
2020-11-06 22:38:46 × dbmikus__ quits (~dbmikus@cpe-76-167-86-219.natsow.res.rr.com) (Read error: Connection reset by peer)
2020-11-06 22:38:50 × knupfer quits (~Thunderbi@mue-88-130-61-134.dsl.tropolys.de) (Ping timeout: 260 seconds)
2020-11-06 22:38:55 × ensyde quits (~ensyde@99-185-235-117.lightspeed.chrlnc.sbcglobal.net) (Read error: Connection reset by peer)
2020-11-06 22:39:04 <ski> (.. and then, when you really need sum types in OO languages, you're often left with only clumsy ways of simulating them. like either using `switch' with downcasts, or `if'-`else's with downcasts. or (more blessed), the VisitorPattern (which is basically a Continuation-Passing / Church Style encoding of sum types))
2020-11-06 22:39:22 dbmikus__ joins (~dbmikus@cpe-76-167-86-219.natsow.res.rr.com)
2020-11-06 22:40:12 <ski> let's say you want to have some type. and you want to be able to construct values of this type, of some number of different alternative forms. and you also want to be able to query values of this type for "properties"
2020-11-06 22:41:08 <ski> if the alternatives that you want to support are relatively fixed, but the properties are likely to be modified, or get extended with new ones, then you probably want sum types
2020-11-06 22:41:44 invaser joins (~Thunderbi@31.148.23.125)
2020-11-06 22:41:45 <ski> if the properties are relatively fixed, but the alternatives you want to support are likely to be modified, or extended, then you probably want product types
2020-11-06 22:42:31 <ski> for each alternative, you need to implement the property (the "method") on that alternative. so, you can draw a table, where the rows are different alternatives, and the columns are different properties
2020-11-06 22:42:45 × borne quits (~fritjof@200116b864a45200fbd62cc7430251a2.dip.versatel-1u1.de) (Quit: WeeChat 2.9)
2020-11-06 22:42:55 ensyde joins (~ensyde@99-185-235-117.lightspeed.chrlnc.sbcglobal.net)
2020-11-06 22:43:15 <ski> and each cell contains the implementation of the property of that column, for the alternative that is the row
2020-11-06 22:44:31 <ski> then, if you slice this table into rows, you're grouping all the property implementations, for a single alternative, together. this is the product type road. such an alternative is called a "class", in the OO world, and the properties are called "methods" (or "member functions" or perhaps some other term as well)
2020-11-06 22:45:58 <ski> so, to add another alternative, you just define a new class, defining all the methods/properties for it. but, to add a new property, you need to add a method to all the existing alternatives/classes (all the classes/alternatives implement the same interface. or maybe they inherit from a common base class, which is likely often abstract)
2020-11-06 22:46:40 <ski> so, adding a new property is harder, more error-prone, since you need to modify existing code, and possibly take into account interactions with that code
2020-11-06 22:47:28 <ski> on the other hand .. if you instead slice the table into separate columns, then each column is the implementation of a single property, for all the different alternatives. this is called a "pattern-matching function"
2020-11-06 22:47:31 <cohn> gonna take me a minute to digest all of that... :D
2020-11-06 22:48:10 × ensyde quits (~ensyde@99-185-235-117.lightspeed.chrlnc.sbcglobal.net) (Ping timeout: 260 seconds)
2020-11-06 22:48:15 <ski> now, adding a new property is simple, you just add a new pattern-matching function, handling all the data constructors (the alternatives) in separate defining equations of the function
2020-11-06 22:48:57 <ski> however, adding (or modifying) a new alternative is more involved, since now you need to go and change all existing pattern-matching functions that takes an input of data type
2020-11-06 22:49:24 <ski> so .. it is a trade-off. neither is fundamentally better than the other. it depends on what you expect
2020-11-06 22:49:52 <ski> also, then there's issues like recursion in your type that complicates this picture. but the above is the basic summary of the difference
2020-11-06 22:51:33 <ski> cohn : as an example : define a type `Shape', meant to describe a simple geometric shape. and say you want to support rectangles (with width,height) and circles (with radius) as possible alternatives. as properties, you want to support circumference and area
2020-11-06 22:51:38 × hyperisco quits (~hyperisco@d192-186-117-226.static.comm.cgocable.net) (Ping timeout: 264 seconds)
2020-11-06 22:51:55 <cohn> right
2020-11-06 22:52:55 × pfurla quits (~pfurla@129.15.195.173.client.static.strong-in52.as13926.net) (Ping timeout: 246 seconds)
2020-11-06 22:52:56 <ski> exercise for you : define `Shape' as a product/record type, with circumference and area as fields/methods. and define functions ("constructors"/"classes" in OO terminology) `rectangle' and `circle', taking width & height, respectively radius, and giving you back a `Shape'
2020-11-06 22:53:13 ensyde joins (~ensyde@99-185-235-117.lightspeed.chrlnc.sbcglobal.net)
2020-11-06 22:53:33 <cohn> ok
2020-11-06 22:54:33 <ski> then, define `Shape' again, but this time as a sum/variant type (algebraic data type), having `Rectangle' (with width & height arguments/components) and `Circle' (with radius component) as alternatives (data constructors), and then define the properties `circumference' and `area' as pattern-matching functions on `Shape'
2020-11-06 22:54:53 <cohn> afk for a sec.
2020-11-06 22:55:10 × invaser quits (~Thunderbi@31.148.23.125) (Ping timeout: 260 seconds)
2020-11-06 22:55:32 Stanley00 joins (~stanley00@unaffiliated/stanley00)
2020-11-06 22:56:34 pfurla joins (~pfurla@ool-182ed2e2.dyn.optonline.net)
2020-11-06 22:57:49 × ensyde quits (~ensyde@99-185-235-117.lightspeed.chrlnc.sbcglobal.net) (Ping timeout: 246 seconds)
2020-11-06 22:57:49 × codygman quits (~codygman@47-184-107-46.dlls.tx.frontiernet.net) (Ping timeout: 246 seconds)

All times are in UTC.