clmg 2017-03-01 05:45:17
How do I use Control.Lens.Plated?
Cale 2017-03-01 05:46:17
merijn: I don't know whether you're looking to scale up to using a full database server at some point, but given that description I'd be tempted just to switch to using something like binary or attoparsec (and pipes?)
c_wraith 2017-03-01 05:46:40
clmg, are you asking about making a type compatible with it, or using its combinators to achieve a particular goal?
merijn 2017-03-01 05:47:09
Cale: No, these are just benchmark results I'm analysing/plotting
clmg 2017-03-01 05:47:26
c_wraith: I'm asking about what to write in the `instance Plated Foo where`
merijn 2017-03-01 05:47:30
Cale: It's just that my dataset has grown to the point where trivial scripts start to become to slow
clmg 2017-03-01 05:47:45
I need some `plate =` but I can't find any examples of how to implement Plated
merijn 2017-03-01 05:48:06
Cale: But that's not a workload that really demands a dedicated server. Especially since having all benchmark results in an SQLite file is nicely portable
clmg 2017-03-01 05:48:39
c_wraith: the structure is `Split = Split { left :: Maybe Split, right :: maybe Split }`
clmg 2017-03-01 05:48:58
I need to traverse these splits without simply deriving data.
merijn 2017-03-01 05:49:20
Cale: 'cause right now I have 50k text files of results, which would be a lot nicer as a single SQLite db :p And I do want to do some filtering/preprocessing in what datapoints I consider, so a straight up attoparsec+pipes thing seems a bit inconvenient
Cale 2017-03-01 05:49:25
clmg: Well, one option is just to add deriving (Data), and then write "instance Plated Split"
clmg 2017-03-01 05:49:48
Cale: but I'll want to add more fields to split soon. like a filepath
clmg 2017-03-01 05:49:55
Cale: can I have filepath derive data also?
c_wraith 2017-03-01 05:50:01
clmg, deriving Data is the easiest, but it's not too bad manually. you just write a traversal that returns its direct children.
Cale 2017-03-01 05:50:12
Does it not already?
clmg 2017-03-01 05:50:18
Cale nope
Cale 2017-03-01 05:50:23
ah, fair enough
Cale 2017-03-01 05:50:38
well, you can just write the traversal directly
clmg 2017-03-01 05:50:57
Cale: any examples other than the cryptic one on hackage?
Cale 2017-03-01 05:51:09
https://hackage.haskell.org/package/lens-4.15.1/docs/src/Control.Lens.Plated.html#Plated
Cale 2017-03-01 05:51:41
not as many good examples as I'd have hoped
Cale 2017-03-01 05:51:48
But the one for lists sort of gives the idea
c_wraith 2017-03-01 05:52:02
clmg, it's just a Traversal. if you work from the type, it's pretty obvious what it has to do.
clmg 2017-03-01 05:53:07
c_wraith: okay so it's traversing a list. (x:xs) is obvious. [] is obvious. What is f?
Cale 2017-03-01 05:53:31
type Traversal s t a b = forall f. Applicative f => (a -> f b) -> s -> f t
Cale 2017-03-01 05:53:48
and here, s, t, a, b are all your type
c_wraith 2017-03-01 05:54:08
f is whatever function is passed in. it's opaque. don't worry about what it *is*, just use it.
Cale 2017-03-01 05:54:31
So you want to write something of type Applicative f => (Split -> f Split) -> Split -> f Split
clmg 2017-03-01 05:55:02
I think I'm in over my head a bit
clmg 2017-03-01 05:55:09
thanks guys
leshow 2017-03-01 05:55:17
i thought traverse's type was (a -> f b) -> t a -> f (t b)
c_wraith 2017-03-01 05:55:55
clmg, as an alternative, if Split has lenses for left and right, you can build the traversal out of combinators.
lyxia 2017-03-01 05:56:06
leshow: the idea is that Split is isomorphic to t Split for some t.
c_wraith 2017-03-01 05:56:25
leshow, Traversal is a generalization of that
c_wraith 2017-03-01 05:57:23
clmg, plate = leftLens . _Just <> rightness . _Just
c_wraith 2017-03-01 05:58:28
clmg, though in all honesty, that's more complicated than just writing it by hand.
Cale 2017-03-01 05:58:30
plate f (Split l r) = Split <$> traverse f l <*> traverse f r
Cale 2017-03-01 05:58:35
^^ easier
clmg 2017-03-01 05:58:51
Cale: awesome this is really really helpful
c_wraith 2017-03-01 06:00:05
as I said, writing it directly is a lot easier. :)
clmg 2017-03-01 06:01:36
what if I want to add more fields to that record. where do that factor into the plate?
ertes 2017-03-01 06:02:16
:t \f (x, y) = (,) <$> f x <*> f y
lambdabot 2017-03-01 06:02:18
error:
lambdabot 2017-03-01 06:02:18
parse error on input '='
lambdabot 2017-03-01 06:02:18
Perhaps you need a 'let' in a 'do' block?
ertes 2017-03-01 06:02:23
:t \f (x, y) -> (,) <$> f x <*> f y
lambdabot 2017-03-01 06:02:25
Applicative f => (t -> f a) -> (t, t) -> f (a, a)
c_wraith 2017-03-01 06:02:37
clmg, just add them to the pattern match. unless they are also recursive, they don't need to be used in the body of plate
ertes 2017-03-01 06:02:48
clmg: ^ a traversal for both components of a tuple
ertes 2017-03-01 06:03:02
@let myBoth f (x, y) = (,) <$> f x <*> f y
lambdabot 2017-03-01 06:03:05
Defined.
ertes 2017-03-01 06:03:21
> (myBoth +~ 2) & (4, 7)
lambdabot 2017-03-01 06:03:26
error:
lambdabot 2017-03-01 06:03:26
• Couldn't match expected type '((Integer, Integer)
lambdabot 2017-03-01 06:03:26
-> (Integer, Integer))
Cale 2017-03-01 06:03:27
you might end up replacing the use of the constructor on the left of the <$> with a lambda that replaces the unchanging fields
c_wraith 2017-03-01 06:03:39
clmg, wait, that's not true. they do need to be used to construct the result Spkit
c_wraith 2017-03-01 06:03:43
.. Split
ertes 2017-03-01 06:03:53
> (myBoth +~ 2) (4, 7)
lambdabot 2017-03-01 06:03:57
(6,9)
Cale 2017-03-01 06:04:08
e.g. plate f (Split l x r) = (\l' r' -> Split l' x r') <$> traverse f l <*> traverse f r
c_wraith 2017-03-01 06:04:13
clmg, basically, it's the only change you can make that still compiles
ertes 2017-03-01 06:04:21
> ("hello ", "world") ^. myBoth
lambdabot 2017-03-01 06:04:24
"hello world"
clmg 2017-03-01 06:06:19
c_wraith: that compiles
clmg 2017-03-01 06:06:37
c_wraith: great :)
c_wraith 2017-03-01 06:06:51
clmg, the compiler is your friend. it tells you what you need to do. it just speaks an odd dialect that takes a while to get used to :)
Cale 2017-03-01 06:06:52
Yeah, looking at the traversal for both elements of a pair that ertes showed ought to be instructive
raynold 2017-03-01 06:07:55
ahh it's a wonderful day
clmg 2017-03-01 06:07:58
thanks chan
Cale 2017-03-01 06:08:56
You can think of a traversal as separating a data structure into the part outside the elements being traversed, which gets encoded as a function of those elements, sort of like it's the original data structure with holes blown in it, and then each of the elements you're traversing, which have the arbitrary function applied to them and then everything gets combined together with the Applicative combinators
Cale 2017-03-01 06:10:01
(at least, this always works for the cases where there's only finitely many things you're traversing over)
ertes 2017-03-01 06:10:48
another interpretation: a traversal takes apart a structure, applies an effectful function to it, and then reassembles it into the same structure, but with the results
ertes 2017-03-01 06:11:39
myBoth f (x, y) {- here we take apart the tuple -} = (,) {- here we reassemble it -} <$> f x <*> f y -- after applying the effectful function to each component
dolio 2017-03-01 06:12:13
Cale: Works all the time. You just can't pretend it's a list for infinite cases.
dolio 2017-03-01 06:12:54
(Except infinite lists.)
Cale 2017-03-01 06:13:02
dolio: Well, you can't... have a function with infinitely many parameters
Cale 2017-03-01 06:13:07
But yeah
ertes 2017-03-01 06:13:43
with do-notation (e.g. -XApplicativeDo) it might be a bit clearer: myBoth f {- take apart: -} (x', y') = do {- apply effect for each component: -} x <- f x'; y <- f y'; {- reassemble: -} pure (x, y)
joe9 2017-03-01 06:15:54
any rainbox users, please? Did you install it with stack? https://hackage.haskell.org/package/rainbox
ski 2017-03-01 06:34:24
Cale : hmm, reminds me of something i've been thinking about ..