rlk*_*024 4 haskell functional-programming lenses
假设我有以下内容:
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
data Book = Book {
_author :: String,
_title :: String
} deriving (Show)
makeLenses ''Book
data Location = Location {
_city :: String,
_state :: String
} deriving (Show)
makeLenses ''Location
data Library = Library {
_location :: Location,
_books :: [Book]
} deriving (Show)
makeLenses ''Library
lib :: Library
lib = Library (Location "Baltimore" "MD") [Book "Plato" "Republic", Book "Aristotle" "Ethics"]
Run Code Online (Sandbox Code Playgroud)
我试图通过组合镜头来了解通过多层向下延伸的各种方法.我知道如何做这些操作:
-- returns "Baltimore"
lib ^. location . city
-- returns a copy of lib with the city replaced
set (location . city) "Silver Spring" lib
Run Code Online (Sandbox Code Playgroud)
但是,如果我想改变书名怎么办?也许我想改变它们全部使用map,或者我只是想改变第三个使用!! 2?我似乎应该为此制作一个新镜头.我认为我应该用books和title中间功能组合镜头,即map或!!.
books . (!! 2) . title
-- or
books . map . title
Run Code Online (Sandbox Code Playgroud)
我该怎么办呢?
> over (books . traverse . title) (++" hi") lib
Library {_location = Location {_city = "Baltimore", _state = "MD"}, _books = [Book {_author = "Plato", _title = "Republic hi"},Book {_author = "Aristotle", _title = "Ethics hi"}]}
Run Code Online (Sandbox Code Playgroud)
traverse允许您处理列表中的每个元素.如果要生成列表中的一个元素,则使用elementa Int来指示处理的索引.
> over (books . element 0 . title) (++" hi") lib
Library {_location = Location {_city = "Baltimore", _state = "MD"}, _books = [Book {_author = "Plato", _title = "Republic hi"},Book {_author = "Aristotle", _title = "Ethics"}]}
Run Code Online (Sandbox Code Playgroud)
希望有所帮助.