gpt4 book ai didi

haskell - Haskell中一般函数变换的一个案例

转载 作者:行者123 更新时间:2023-12-03 06:28:29 26 4
gpt4 key购买 nike

我正在(尝试)学习 Haskell 中的可变状态。为了简单起见,我定义了

data Car = Car { position :: Int }

move :: Car -> Int -> Car
move c n = Car { position = n + (position c) }

因此,move 是一个“纯”函数,表示从一辆汽车转换到另一辆汽车。

我认为我需要将汽车保存在可变变量中,以便我可以获得当前位置(在对汽车进行一些移动之后)。因此我定义(我希望这是要走的路,否则请纠正我)以下

type Parking = IORef Car -- holds a car

newParking :: Car -> IO Parking
newParking = newIORef

以及简单的 getCar::Parking -> IO CarsetCar::Parking -> Car -> IO () 函数。

上面的代码看起来没问题。

问题:

我可以定义一个函数,将任何纯函数(例如move::Car -> Int -> Car)转换为函数Parking -> Int -> ()move 应用于停放的汽车并将其替换为新汽车?

合并已接受答案后的示例

import Data.IORef
import Control.Concurrent

-- -----------------------------------------------------

timeGoesBy place = do
moveTheCar place
threadDelay 1000000
timeGoesBy place

moveTheCar place = do
car <- getCar place
print $ getPos car
modifyCar place (move 7)

-- -----------------------------------------------------
main = do
place <- newParking (newCar 1000)
timeGoesBy place
print "end"

-- -----------------------------------------------------

type Parking = IORef Car -- mutable var for holding a car (the car may be replaced)

newParking :: Car -> IO Parking
newParking = newIORef

getCar :: Parking -> IO Car
getCar = readIORef

setCar :: Parking -> Car -> IO ()
setCar = writeIORef

modifyCar :: Parking -> (Car -> Car) -> IO ()
modifyCar = modifyIORef

-- -----------------------------------------------------

data Car = Car { position :: Int } -- Car data type ("pure")

-- create a car
newCar :: Int -> Car
newCar v = Car { position = v}

-- get the position of a car
getPos :: Car -> Int
getPos c = (position c)

-- move : transform a given car into a new "moved car"
move :: Int -> Car -> Car -- first the int so that we can curry (i.e. move 7)
move n car = Car { position = n + (position car) }

最佳答案

或者,我们可以使用 State Monad 来避免/实际/可变性。

import Control.Monad.State

定义汽车结构

data Car = Car { position :: Int } deriving Show

启动状态,我们使用execState,给它一个保存状态和初始状态(Car 0)的函数。

start :: Car
start = execState myState (Car 0)

移动会移动你的车

move :: Int -> Car -> Car
move n c = c { position = n + position c }

doStuff 将帮助您更轻松地将函数应用于 State Monad,“get”为我们提供当前状态(Car 0),而“put”则将新版本放入该状态。我们首先得到它,对其应用 f,然后将其置于新状态。

doStuff :: MonadState a m => (a -> a) -> m ()
doStuff f = get >>= put . f

这是 State 函数,这里我们简单地用 move 1 调用 doStuff ,它会修改我们的汽车(Car 0)以移动 1 Int,所以新的结果将是 Car 1。然后我们说 move 3 ,它'将换乘4号车

myState :: State Car ()
myState = do
doStuff $ move 1
doStuff $ move 3

这样我们就可以运行启动函数并接收修改后的初始字母(Car 0)。

关于haskell - Haskell中一般函数变换的一个案例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21162032/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com