I'm experimenting with some ideas and I think one of the problems I have could be solved with lenses, but it doesn't seem to work how I expect it to when I try to implement it.
I want to create a tree of data structures, where each node stores a lens that goes from the root of the tree down to that node. Here is a conceptual image. The idea in that image is that the color of the lens matches the color of the path that it represents through the tree.
Here is an example of a tree shaped data structure without storing the path lenses at the nodes:
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
data Child a = Child { _value :: a } deriving (Show)
data Root = Root { _child1 :: Child Int, _child2 :: Child Char } deriving (Show)
makeLenses ''Child
makeLenses ''Root
main = do
let tree = Root (Child 1) (Child 'a')
print $ tree ^. child2 . value
Here is the same example, but now I've added a separate data type to represent the nodes explicitly and I again use a lense to traverse the tree.
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
data Child a = Child { _value :: a }
data Root = Root { _child1 :: Tree (Child Int), _child2 :: Tree (Child Char) }
data Tree a = Tree { _content :: a }
makeLenses ''Child
makeLenses ''Root
makeLenses ''Tree
main = do
let c1 = Tree (Child 1)
c2 = Tree (Child 'a')
root = Tree (Root c1 c2)
print $ root ^. content . child1 . content . value
print $ root ^. content . child2 . content . value
Finally, this is what I would like to end up with:
{-# LANGUAGE TemplateHaskell, NoMonomorphismRestriction #-}
import Control.Lens
data Child a = Child { _value :: a }
data Root a b = Root { _child1 :: Tree a (Child Int), _child2 :: Tree b (Child Char) }
data Tree c a = Tree { context :: c, _content :: a }
makeLenses ''Child
makeLenses ''Root
makeLenses ''Tree
main = do
let c1 = Tree (content . child1 . content) (Child 1)
c2 = Tree (content . child2 . content) (Child 'a')
root = Tree (content) (Root c1 c2)
print $ root ^. (context c1) . value
But this implementation give me this error on the line with the print
statement:
No instance for (Functor f2) arising from a use of ‘root’
The type variable ‘f2’ is ambiguous
Note: there are several potential instances:
instance Functor ((,) a) -- Defined in ‘GHC.Base’
instance Functor ((->) r) -- Defined in ‘GHC.Base’
instance Functor IO -- Defined in ‘GHC.Base’
...plus 11 others
In the first argument of ‘(^.)’, namely ‘root’
In the first argument of ‘print’, namely
‘(root ^. (c1 ^. context) . value)’
In a stmt of a 'do' block: print (root ^. (c1 ^. context) . value)
I don't really understand what is expected of me here. Any advice?