Haskell中对不可变数据的可变引用
我想在一系列不变的值中跟踪“当前”值。 在Haskell中,不为每个新值引入新引用的最佳方法是什么? 以下是一个例子:Haskell中对不可变数据的可变引用,haskell,immutability,frege,Haskell,Immutability,Frege,我想在一系列不变的值中跟踪“当前”值。 在Haskell中,不为每个新值引入新引用的最佳方法是什么? 以下是一个例子: data Person = Person {name, level, topic :: String } deriving(Show) dierk :: Person dierk = Person "Dierk" "confident" "Java" works :: Person -> String works person = name person ++
data Person = Person {name, level, topic :: String }
deriving(Show)
dierk :: Person
dierk = Person "Dierk" "confident" "Java"
works :: Person -> String
works person = name person ++ " is " ++ level person ++ " in " ++ topic person
main _ = do
putStrLn $ works dierk
-- do more with "current" topic
putStrLn $ works dierk {level= "proficient", topic="Groovy"}
-- do more with "current" topic
putStrLn $ works dierk {level= "dabbling", topic="Haskell"}
-- do more with "current" topic
我不确定这个问题到底要问什么。发布的示例 可以重写以使用
StateT Person IO
monad,如下所示
import Control.Monad.State
data Person = Person {name, level, topic :: String }
deriving Show
dierk :: Person
dierk = Person "Dierk" "confident" "Java"
works :: Person -> String
works person = name person ++ " is " ++ level person ++ " in " ++ topic person
main :: IO ()
main = flip evalStateT dierk $ do
-- use the current topic
lift . putStrLn . works =<< get
-- change the current topic
modify (\t -> t{level= "proficient", topic="Groovy"})
lift . putStrLn . works =<< get
-- change the current topic
modify (\t -> t{level= "dabbling", topic="Haskell"})
lift . putStrLn . works =<< get
{- Output:
Dierk is confident in Java
Dierk is proficient in Groovy
Dierk is dabbling in Haskell
-}
import Control.Monad.State
data Person=Person{name,level,topic::String}
衍生节目
迪尔克:人
dierk=人“dierk”“自信”“Java”
works::Person->String
works person=姓名person++”是“+++主题person”中的“+++级别person++”
main::IO()
main=flip evalStateT dierk$do
--使用当前主题
举起putStrLn。works=t{level=“profession”,topic=“Groovy”})
举起putStrLn。works=t{level=“dabbling”,topic=“Haskell”})
举起putStrLn。works=总结一下,给像我这样的Haskell新手一些提示——下面是我最终解决的解决方案。这不是伪代码:-),而是Frege(JVM的Haskell),它有一些细微的符号差异
module Person where
import frege.control.monad.State
data Person = Person {name, level, topic :: String }
derive Show Person
dierk = Person "Dierk" "confident" "Java"
works :: Person -> String
works person = person.name ++ " is " ++ person.level ++ " in " ++ person.topic
printCurrentPerson :: StateT Person IO ()
printCurrentPerson = do
person <- StateT.get -- independent of any particular person reference
StateT.lift $ println $ works person
updateCurrentPerson :: Monad m => String -> String -> StateT Person m ()
updateCurrentPerson level topic = do
StateT.modify (\person -> Person.{level= level, topic=topic} person)
usingMutableRefsToImmutableState :: Person -> IO ((),Person)
usingMutableRefsToImmutableState start =
flip StateT.run start $ do
printCurrentPerson
updateCurrentPerson "proficient" "Groovy"
printCurrentPerson
StateT.lift $ println "-- user input could influence which selection is 'current' "
updateCurrentPerson "dabbling" "Haskell"
printCurrentPerson
main = do -- using the StateT transformer to work in combination with any monad (here: IO)
(_, lastPerson) <- usingMutableRefsToImmutableState dierk
println "-- a second round with relaying the last person"
_ <- usingMutableRefsToImmutableState lastPerson
return ()
{- output
Dierk is confident in Java
Dierk is proficient in Groovy
-- user input could influence which selection is 'current'
Dierk is dabbling in Haskell
-- a second round with relaying the last person
Dierk is dabbling in Haskell
Dierk is proficient in Groovy
-- user input could influence which selection is 'current'
Dierk is dabbling in Haskell
-}
模块人员在哪里
进口frege.control.monad.State
data Person=Person{name,level,topic::String}
演艺人员
dierk=人“dierk”“自信”“Java”
works::Person->String
works person=person.name++“是“++person.topic”中的“++person.level++”
printCurrentPerson::StateT Person IO()
printCurrentPerson=do
人员字符串->字符串->状态人员m()
updateCurrentPerson级别主题=do
StateT.modify(\person->person.{level=level,topic=topic}person)
使用mutableRefstoImmutableState::Person->IO((),Person)
使用MutableRefstoImmutableState启动=
flip StateT.run开始$do
打印当前人
updateCurrentPerson“精通”Groovy
打印当前人
StateT.lift$println”--用户输入可能会影响哪个选择是“当前的”
updateCurrentPerson“涉猎”Haskell
打印当前人
main=do——使用StateT转换器与任何monad一起工作(此处:IO)
(最后一个人)这要看情况。可变性可以通过状态人
单子获得。如果你还需要在IO上面做IO,那么你可能需要“>代码> StItEnter IO < /Cord>。状态单元格并没有切断它,因为你只得到状态继承(每一个变化都有新的状态),但是没有提到“当前”状态。“引用当前状态”,确切地说?它不能是某个值current::Person
,因为它是不可变的。您可能正在寻找类似IORef
的内容。谢谢,这肯定是我问题的解决方案。