LINUX.ORG.RU

Haskell обощённая работа с запясями


0

1

В запись хранит списки. Необходимо в эти списки добавлять новые элементы. Типы списков разные. Сейчас это делается так (для каждого поля своя функция add)z

data T = T {a :: [T1], b :: [T2]}
add state v = let T {a = vs} = state in
              state {a = v:vs}
Очень хочется обощить функцию add так, что бы имя поля можно было передавать внутрь функции, вызывая ей примерно так: add a state v.

Возможно ли это выразить (интуитивно, это может быть как-то выражено с использованием экзистенциальных типов, но как)?

Ответ на: комментарий от ryukzak

Ну тогда классы типов.

data T1 = T1
        deriving Show

data T2 = T2
        deriving Show

data T = T [T1] [T2]
       deriving Show

class TAddable t where
  add :: T -> t -> T

instance TAddable T1 where
  add (T ts1 ts2) t1 = T (t1:ts1) ts2

instance TAddable T2 where
  add (T ts1 ts2) t2 = T ts1 (t2:ts2)
*Main> add (T [] []) T1
T [T1] []
*Main> add (T [] []) T2
T [] [T2]
*Main> (T [] []) `add` T2 `add` T1 `add` T1
T [T1,T1] [T2]
sanuda
()
Ответ на: комментарий от sanuda

Вариант неплохой, но тоже не сильно обощённый. Надо писать по add для каждого типа. + если типы в записе пересекаться будут, то работать не будет.

Интересен вариант предложенный ratatosk. Правда каждый add необходимо сопроводить и геттером и сеттером. Много кода, но всё-таки меньше.

ryukzak
() автор топика
Ответ на: комментарий от ryukzak

Или если совсем в лоб, то так. [code] data T = T {a :: [T1], b :: [T2]} add g s state v = let T vs = g state in s state v:vs

getA T{a = v} = v setA state v = state {a = v} [/code]

ryukzak
() автор топика
Ответ на: комментарий от ryukzak

Надо писать по add для каждого типа.

А где не надо?

+ если типы в записе пересекаться будут, то работать не будет.

Тогда раскрой класс и сделай указание инстансов вручную.

data Tlass t = Tlass (T -> t -> T)

t1 :: Tlass T1
t1 = Tlass (\(T ts1 ts2) t -> T (t:ts1) ts2)

t2 :: Tlass T2
t2 = Tlass (\(T ts1 ts2) t -> T ts1 (t:ts2))

add :: Tlass t -> T -> t -> T
add (Tlass f) = f
*Main> add t1 (T [] []) T1
T [T1] []
*Main> add t2 (T [] []) T2
T [] [T2]
sanuda
()

data-accessor или всякие его аналоги. Мне вот fclabels по описанию понравилось. Ещё есть, скажем, data-lens-fd. Короче, погрепай hackage по слову record :)

Portnov
()
Ответ на: комментарий от sanuda

> По делу есть что сказать?

Куда уж более по делу? Хаски — негибкий, нерасширяемый язык, который неспособен решить проблему ТСа. Что не так?

anonymous
()
Ответ на: комментарий от anonymous

Твой бред не так. Предложено не менее 4 различных подходов.

sanuda
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.