4

假设我有以下内容:

{-# 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"]

我试图通过构成镜头来了解通过多层向下延伸的各种方法。我知道如何进行这些操作:

-- returns "Baltimore"
lib ^. location . city

-- returns a copy of lib with the city replaced
set (location . city) "Silver Spring" lib

但是,如果我想更改书名怎么办?也许我想用 来改变它们map,或者我只想用 改变第三个!! 2?看来我应该为此制作一个新镜头。我想我应该用一个中间函数来组成booksandtitle镜头,即mapor !!

books . (!! 2) . title
-- or
books . map . title

我该怎么做呢?

4

1 回答 1

8

muhmuhten 是正确的,您应该阅读镜头包中的遍历。

> 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"}]}

traverse允许您处理列表中的每个元素。如果要影响列表的一个元素,则使用elementwhichInt表示处理的索引。

> 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"}]}

希望有帮助。

于 2013-09-02T22:52:32.147 回答