2011-12-14 7 views
6

У меня есть Haskell шаблонного, который выглядит примерно так:Haskell динамического типа данных изменения

data Configuration 
    { confA :: Integer 
    , confB :: Boolean 
    , confC :: String } 

x = (\arg opt -> opt{ confA=arg }) 
y = (\arg opt -> opt{ confB=arg }) 
z = (\arg opt -> opt{ confC=arg }) 

, и я хотел бы, чтобы удалить шаблонные, получая что-то вдоль линий:

setter :: (Config -> a) -> a -> Config -> Config 
x = setter confA 
y = setter confB 
z = setter confC 

Но я не знаю, как построить такую ​​функцию setter. Возможно ли это в (без шаблона) haskell, или я не против использования синтаксиса сахара здесь? Если да, то как мне это сделать в шаблоне haskell?

ответ

13

Это невозможно с помощью системы учета Haskell. Вам нужны линзы; это previous Stack Overflow question и его главный ответ - хорошее введение. Лично я использую пакет data-lens, о котором там говорили. (Смотрите также data-lens-fd использовать его с MonadState класса от MTL - если вы не знаете, что это такое, просто знаю, что вы должны, вероятно, использовать его всякий раз, когда вы хотите использовать линзы в State монады.)

data-lens-template пакет может быть применением шаблона Haskell, которого вы хотите; он определяет определения объективов для полей записи.

Другой популярный комплект объективов - fclabels. Я предпочитаю объектив данных для его простоты и скорости; fclabels (начиная с версии 1.0) немного более гибкая, но вам не нужна такая гибкость для того, что вы хотите сделать. (Обратите внимание, что из-за своей новой гибкости тип fclabels (:->) больше не может быть непосредственно переведен на простое определение линз, как указано в ответе на переполнение стека, который я связал.)

1

Это невозможно без шаблона Haskell. Вы можете использовать шаблон доступа к данным и шаблон доступа к данным для удаления такой плиты котла.

+0

Я считаю, что это правильно. Синтаксис записи автоматически создает * getters * для вас, но это в основном бесполезно, если вы хотите создать * seters *. –

Смежные вопросы