假设:
我们可以看到我们可以在Haskell中创建lens like this:
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
initialState :: Game
initialState = Game
{ _score = 0
, _units =
[ Unit
{ _health = 10
, _position = Point { _x = 3.5, _y = 7.0 }
}
]
}
health :: Lens' Unit Int
health = lens _health (\unit v -> unit { _health = v })
它的目的是从health
数据结构中获取game
值。
我们可以在Clojure中进行解构like this:
user=> (def book {:name "SICP" :details {:pages 657 :isbn-10 "0262011530"}})
#'user/book
user=> (let [{name :name {pages :pages isbn-10 :isbn-10} :details} book]
(println "name:" name "pages:" pages "isbn-10:" isbn-10))
name: SICP pages: 657 isbn-10: 0262011530
目的是从嵌套结构中获取名称,页面等的嵌套值。
在这两种情况下,您都会想出一种机制,可以从嵌套结构中重用来检索值。
我的问题是: Haskell中的镜头与Clojure中的解构有什么相似之处?
答案 0 :(得分:3)
你的Clojure代码最接近于Haskell中的表达方式:
book :: Book
book = Book {name = "SICP", details = Details {pages = 657, isbn_10: "0262011530"}}
main = do
let Book {name = name, details = Details {pages = pages, isbn_10 = isbn_10}} = book
putStrLn $ "name:" ++ name ++ "pages:" ++ (show pages) ++ "isbn-10:" ++ isbn-10
这里我们使用Haskell的模式匹配,这基本上是Clojure的解构绑定的一般形式,以获得记录的内容。这与镜头无关。
现在让我们看一下带镜头的Haskell代码。此代码有三种记录类型,Game,Unit和Point,这些类型都有一组自动定义的函数来访问其成员而不进行模式匹配。这些函数称为_score
,_health
,_x
等等(就像成员名称一样)。他们分别获得Game
,Unit
或Point
并生成其各自成员的价值。如果必须手动定义这些函数(因为Haskell自动为所有记录类型定义了这些函数),它们看起来像这样:
_health (Unit {health = h}) = h
到目前为止,这仍与镜片无关。
代码中的镜头为health
。它包含函数_health
(如上所述,它采用Unit
并生成其健康状况)和函数(\unit v -> unit { _health = v })
,它采用单位和值并生成一个新的单位,其健康状况已设置为该值。换句话说,镜头包含获取和设置单位健康的代码。镜头库现在包含各种功能,您可以使用它们来构图和使用这些镜头。
所以回答你的问题:镜片和解构之间没有相似之处。