Alb*_*ani 2 haskell haskell-lens
1)我需要将字段构造函数参数传递给函数。我做了一些测试,但我无法这样做。是否可以?否则,是否可以使用镜头包装?
2) 是否可以在 MonadState 中使用修改来修改字段?(我做了几次尝试,但没有成功。例如: modify (second = "x") 不起作用。
import Control.Monad.State
data Test = Test {first :: Int, second :: String} deriving Show
dataTest = Test {first = 1, second = ""}
test1 = runStateT modif1 dataTest -- OK
test2 = runStateT (modif2 "!") dataTest -- OK
test3 = runStateT (modif3 second) dataTest -- WRONG
-- modif1 :: StateT Test IO ()
modif1 = do
st <- get
r <- lift getLine
put $ st {second = "x" ++ r}
-- modif2 :: String -> StateT Test IO ()
modif2 s = do
stat <- get
r <- lift getLine
put $ stat {second = "x" ++ r ++ s}
-- modif3 :: ???? -> StateT Test IO ()
modif3 fc = do
stat <- get
r <- lift getLine
put $ stat {fc = "x" ++ r}
-- When i try to load the module, this is the result:
-- ghc > Failed:
-- ProvaRecord.hs:33:16:`fc' is not a (visible) constructor field name
Run Code Online (Sandbox Code Playgroud)
正如您所说,您可能正在寻找镜头。镜头是允许读取、设置或修改给定字段的值。通常使用Control.Lens,您可以使用下划线定义字段,并makeLenses用于创建功能齐全的镜头。
有许多组合器允许镜头在MonadState. 在您的情况下,我们可以使用%=,在这种情况下将专门用于键入
(MonadState s m) => Lens' s b -> (b -> b) -> m ()
Run Code Online (Sandbox Code Playgroud)
它使用给定的镜头和对内部值进行操作的函数来修改状态值。
您的示例可以使用镜头重写如下:
{-# LANGUAGE TemplateHaskell, RankNTypes #-}
import Control.Lens
import Control.Monad.State
data Test = Test { _first :: Int
, _second :: String
}
deriving Show
-- Generate `first` and `second` lenses.
$(makeLenses ''Test)
-- | An example of a universal function that modifies any lens.
-- It reads a string and appends it to the existing value.
modif :: Lens' a String -> StateT a IO ()
modif l = do
r <- lift getLine
l %= (++ r)
dataTest :: Test
dataTest = Test { _first = 1, _second = "" }
test :: IO Test
test = execStateT (modif second) dataTest
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
446 次 |
| 最近记录: |