モナドを実装する次のコードがあります。後で、より複雑なロジックでフィールドの設定を簡素化するためにそれを使用しようとしています。
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)
このコードは機能しますが、changeAlpha関数を単純化するためにTemplateHaskellを使用したいと思います。このようなものがあれば素晴らしいでしょう:
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
バリエーションはありません。これは可能ですか?