Каковы сходства и различия между объективом в Haskell и использованием последовательности клавиш в Clojure?
Предположения:
- Я знаю, что Haskell поощряет решение проблем с системой типов, а Clojure избегает системы типов, предпочитая решать проблемы со структурами данных.
Мы видим, что мы можем создать такой объектив в Хаскеле:
{-# 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:
(def initialState {:score 0
:units {:health 10
:position {:x 3.5
:y 7.0}}})
(def health [:units :health])
(defn initialState-getter [lens]
(get-in initialState lens))
(initialState-getter health)
> 10
(defn initialState-setter [lens value]
(assoc-in initialState lens value))
(initialState-setter health 22)
> {:score 0, :units {:health 22, :position {:y 7.0, :x 3.5}}}
Здесь мы видим, как вложенная структура обновляется с помощью последовательности клавиш.
Мой вопрос: каковы сходства и различия между объективом в Haskell и использованием последовательности клавиш в Clojure?
1 ответ
Линзы в Haskell не ограничиваются ключами. Например, вы можете написать линзу для длины строки:
lengthLens = lens length setLength
setLength s l = take l s ++ take (l - length s) (repeat '\0')
Последовательности ключей Clojure ограничены ключами map / vector / etc. Лично я не думаю, что это потеря, так как у меня никогда не было необходимости в линзах для не ключоподобных геттеров и сеттеров.
Что касается типов против данных, то состав линзы в Haskell - это данные, очень похожие на функции, это данные. Это похоже на то, как векторы ключей являются данными в Clojure.