Шаблон Haskell с именем поля записи в качестве переменной?

У меня есть следующий фрагмент кода, реализующий монаду. Я пытаюсь использовать его для упрощения настройки полей с более сложной логикой позже.

data Rec = Rec {
    alpha :: Int,
    beta  :: Double,
} deriving (Show)
defaultRec = Rec 0 0 0

data Record r = Record { runRecord :: Rec -> (Rec, r) }
instance Monad Record where
    return r = Record $ \s -> (s, r)
    a >>= b  = Record $ \s -> let (q, r) = runRecord a s in runRecord (b r) q

createRecord f = fst $ runRecord f defaultRec

changeAlpha x  = Record $ \s -> (s { alpha = x }, ())

Я бы использовал следующий код:

myRecord = createRecord (changeAlpha 9)

Этот код работает, но я бы хотел использовать Template Haskell для упрощения функции changeAlpha. Было бы здорово иметь что-то вроде этого:

changeBeta x = $(makeChange beta) x

Я дошел до этого:

changeBeta x = Record $ $([| \z -> \s -> (s { beta = z }, ()) |]) x

Но как только я поменяю его на это:

changeBeta f x = Record $ $([| \z -> \s -> (s { f = z }, ()) |]) x

Я получаю следующее:

TestTH.hs:21:49: `f' is not a (visible) constructor field name

Никакие варианты не работают . Возможно ли это?

9
задан Ana 12 December 2011 в 01:37
поделиться