Каковы сходства и различия между объективом в 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.

Другие вопросы по тегам