2012-02-04 4 views
3

я могу создавать и ссылаться на относительные указатели на структуру членов в C++ с использованием ::*, .* и ->* синтаксиса как:Есть ли у Haskell указатели/ссылки на записи участников?

char* fstab_t::*field = &fstab_t::fs_vfstype; 
my_fstab.*field = ... 

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

(idxF_s,idxL_s) = swap_by_sign sgn (idxF,idxL) ; 

AFAIK, я не могу, однако затем обновлять записи с помощью этих методов получения в качестве меток, таких как:

a { idxF_s = idxL_s b } 

Есть ли простой способ сделать это без кодирования для каждого записывающего устройства?

+1

Указатель на операторы-члены не C, а C++. Retagged. –

ответ

10

Геттер и сеттер, объединенные в первоклассное значение, называются объективом . Для этого существует немало пакетов; наиболее популярными являются data-lens и fclabels. Это previous SO question - хорошее введение.

Обе из этих библиотек поддерживают получение линз из определений записей с использованием шаблона Haskell (с объективом данных, он предоставляется как an additional package для переносимости). Ваш пример будет выражаться в виде (с использованием синтаксиса данных объектива):

setL idxF_s (b ^. idL_s) a 

(или что то же самое: idxF_s ^= (b ^. idL_s) $ a)

Вы можете, конечно, преобразование линзы в общем виде путем преобразования их геттер и сеттер вместе :

-- I don't know what swap_by_sign is supposed to do. 
negateLens :: (Num b) => Lens a b -> Lens a b 
negateLens l = lens get set 
    where 
    get = negate . getL l 
    set = setL l . negate 

(или, что эквивалентно: negateLens l = iso negate negate . l)

В родов l, я бы рекомендовал использовать линзы всякий раз, когда вам приходится иметь дело с любым видом нетривиальной обработки записей; они не только упрощают чистое преобразование записей, но и оба пакета содержат удобные функции для доступа и изменения состояния государственной монады с использованием объективов, что невероятно полезно. (Для данных хрусталика, вы хотите использовать data-lens-fd пакет, чтобы использовать эти функции, удобство в любом MonadState, опять же, они находятся в отдельном пакете для портативности.)


При использовании любого пакет, вы должны начать свои модули с:

import Prelude hiding (id, (.)) 
import Control.Category 

Это потому, что они используют обобщенные формы id и (.) функций прелюдии в - id могут быть использованы в качестве объектива от любого значения к себе (не все, что полезно, по общему признанию,), и (.) используется для создания линз (например, getL (fieldA . fieldB) a - то же, что и getL fieldA . getL fieldB $ a). Более короткое определение negateLens использует это.

5

Что вы хотите здесь, это первоклассные звукозаписывающие лейблы, и хотя этого не существует на этом языке, в Hackage есть несколько пакетов, которые реализуют этот шаблон. Один из них - fclabels, который может использовать Template Haskell для создания требуемого шаблона для вас.Вот пример:

{-# LANGUAGE TemplateHaskell #-} 

import Control.Category 
import Data.Label 
import Prelude hiding ((.)) 

data Foo = Foo { _fieldA :: Int, _fieldB :: Int } 
    deriving (Show) 

$(mkLabels [''Foo]) 

main = do 
    let foo = Foo 2 3 

    putStrLn "Pick a field, A or B" 
    line <- getLine 

    let field = (if line == "A" then fieldA else fieldB) 

    print $ modify field (*10) foo 

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

  • Нет связанных вопросов^_^