haskellhaskell-lensaeson

How to build lens expression dynamically?


I have the following code snippet that reads a value specified by a lens (lens-aeson) expression:

import           Control.Lens    ((^?))
import           Data.Aeson      (Value)
import           Data.Aeson.Key  (fromString)
import           Data.Aeson.Lens (key)
import           Data.Text       (pack)

-- >>> readValue
-- Just (String "value")
readValue :: Maybe Value
readValue = json ^? path
  where
    path = key (fromString "key") . key (fromString "of") . key (fromString "interest")
    json = pack "{\"key\": {\"of\": {\"interest\": \"value\"}}}"

Now I want to build the path expression dynamically from a configuration by passing a list ["key","of","interest"] to readValue.

How can I create the path dynamically from the list?


Solution

  • Something like this, I guess:

    readValue = json ^? _Value.path
      where
        path = foldr (.) id [key (fromString t) | t <- ["key", "of", "interest"]]
        json = pack "{\"key\": {\"of\": {\"interest\": \"value\"}}}"
    

    You can fuse the foldr and list comprehension manually if you feel strongly about it.