Вопрос

I have a deeply nested record which I am trying to rebuild from the database. For example, A contains many B records. B records have many C records. C has many Ds. I have functions to query the children of each type of object (f0, f1, and f2 below).

f0 :: A -> [B]
f1 :: B -> [C]
f2 :: C -> [D]

I am looking for an elegant way to implement f3.

f3 :: A -> (A, [(B, [(C, [D])])])

I've read a little bit on Arrows and it feels like they might be a good fit. However, I keep hitting a road block when I try to combine them.

I've started with something like this:

f4 :: A -> (A, [B])
f4 = id &&& f0

which gets me to the first level. However, I'm at a loss to find a way to chain that to another arrow which would map [B], return [(B, [C])]and use that as the second element of the original tuple.

I'm a bit new to Haskell, so please let me know if I need to include any additional information.

Thanks!

Update

Modifying sclv's answer slightly, I now have

data A = A
data B = B
data C = C
data D = D

f0 :: A -> [B]
f0 = undefined

f1 :: B -> [C]
f1  = undefined

f2 :: C -> [D]
f2 = undefined

pairFun f = id &&& f

foo :: A -> (A, [(B, [C])])
foo = fmap (map (pairFun f1)) . pairFun f0

I still can't wrap my mind around how to combine the last function (f2).

Final update

Thanks to sclv, it turns out this can be done like this:

foo = (fmap . map) ((fmap . map) (pairFun f2) . pairFun f1) . pairFun f0
Это было полезно?

Решение

something like this should work (untested):

pairFun f = id &&& f

foo = (fmap . map) ((fmap . map) (pairFun f2) . pairFun f1) . pairFun f0

edit: one way to think about this, by the way, is using conal's model of semantic editor combinators -- http://conal.net/blog/posts/semantic-editor-combinators

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top