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 ++

我想在一系列不变的值中跟踪“当前”值。 在Haskell中,不为每个新值引入新引用的最佳方法是什么? 以下是一个例子:

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
的内容。谢谢,这肯定是我问题的解决方案。