As a voluntary exercise I try to implement van Laarhoven lenses, prisms, traversals, folds and isos. For me, it’s all very abstract, but I feel like I’m making slow progress. Sometimes the intuition doesn’t work for me, then I try to let me guide by the types. When implementing toListOf
I get stuck because “type tetris” doesn’t help anymore:
They start with
toListOf :: Traversal s s a a -> (s -> [a])
where a Traversal s t a b
s is a function
forall f. Applicative f => (a -> f b) -> (s -> f t)
Then, they generalize Traversal s s a a
to
(a -> Const (Endo [a]) a) -> (s -> Const (Endo [a]) s)
and this is the resulting function I try to implement:
toListOf :: ((a -> K (Endo [a]) a) -> (s -> K (Endo [a]) s)) -> (s -> [a])
toListOf t x = undefined
t
is the “Traversal”, x
is of type s
and we expect a result of type [a]
.
My baby steps:
-
t
expects a function froma
toConst (Endo [a]) a
, the only one I could think of isConst . Endo . map . const
. - After applying
t
to it, I get a functionfoo = t $ Const . Endo . map . const :: s -> Const (Endo [a]) s
- Then I have
x
as a value of types
and applyfoo x
, extract the value withgetConst
and finally get anEndo [a]
I have no idea how an Endo [a]
, a function [a] -> [a]
helps me to get a final [a]
value without having an initial list of a
values. Can somebody give me some hints or point out mistakes I made before?
Thanks for your time!