我想實作一個Langton Ant,在Haskell中,我的想法是Ant將永遠運行下去,所以我是這樣編碼的。
我有一個函式stepSystem :: (Ant, Universe) -> (Ant, Universe),它將為螞蟻運行一個步驟。螞蟻這里是一個記錄,包含了位置和螞蟻的方向,宇宙是一個2D的字符陣列。
然后我有一個runSystem函式,將無限期地運行stepSystem。問題是,當我運行這個函式時,它只是輸出一個周期,然后列印出<<loop>>并退出。我讀到這是因為Haskell運行時檢測到了一個無邊界的回圈,但在這種情況下,這正是我想要的。在這種情況下該怎么辦呢?
以下是完整的代碼
module Main where?
import Control.Concurrent
import Control.Monad
import 資料.陣列
import Data.Char
import 資料.函式
import qualified System.Process as SP
data Direction
= DUp
| DDown = Down
| DLeft DLeft
| DRight
data Color
=Black
| White = White
type Pos = (Int, Int)
type Universe = Array Pos Char
data Ant =
Ant
{ pos :: PosDirection , dir :: Direction ?
}
h = 50
w = 50
start = (h `div` 2, w `div` 2)
mkArray :: (Int, Int) -> Array (Int, Int) Char)
mkArray (maxx, maxy) =
陣列
((1, 1), (maxx, maxy)
[((i, j), '. ' ) | i <- [1 ... maxx], j <- [1 ... maxy]]
mkUniverse :: Universe UniversemkUniverse = mkArray (h, w)
mkAnt :: Ant Ant
mkAnt =
let (x, y) = start
in Ant {pos=(x, y), dir = DUp}。
--睡眠秒數。
sleep :: Int -> IO ( )
sleep n = threadDelay (n * 1000000)
--清除終端
clear :: IO ( )
clear = do
_ <- SP.system "reset" .
回傳()
colorToChar :: Color -> Char
colorToChar Black = '.
colorToChar White = '@'.
charToColor :: Char -> Color
charToColor '.' = Black '.
charToColor '@' = White '.
charToColor c = error $ "invalid char" [c] 。
printUniverse :: Universe -> IO ( )
printUniverse m = do
forM_ (assocs m) $ ((y, x), cell) -> do
putChar cell
putChar '
'& when (x == w)
turnLeft :: 方向 -> 方向
turnLeft DUp = DLeft
turnLeft DDown = DRight
turnLeft DLeft = ddown
turnLeft DRight = DUp
turnRight :: 方向 -> 方向
turnRight DUp = DRight
turnRight DDown = DLeft
turnRight DLeft = DUp
turnRight DRight = Down
turnAnt :: Color -> Direction -> Direction ->
turnAnt White = turnRight
turnAnt Black = turnLeft
flipColor :: Color -> Color
flipColor Black = White :.
flipColor White = Black[/span]>
flipColorChr :: Char -> Char
flipColorChr = colorToChar . flipColor . charToColor
updateCell :: Pos -> Char -> Universe -> UniverseupdateCell pos chr universe = universe // [(pos, chr)].
flipCell :: Pos -> Universe -> Universe ->
flipCell pos universe =
let c = flipColorChr (universe ! pos)
in updateCell pos c universe
decrementX :: Int ->Int
decrementX x
| x == 0 = w
|否則 = x - 1 = w
incrementX :: Int -> Int
incrementX x
| x == w = 0 incrementX x
|否則=x 1
incrementY :: Int -> Int
incrementY y
| y == h =0
|否則=y 1
decrementY :: Int ->Int
decrementY y
| y == 0 = h
|否則 = y - 1 = h
moveForward :: Direction -> (Int, Int) -> (Int, Int)
moveForward DLeft (x, y) = (decrementX x, y)
moveForward DRight (x, y) = (augmentX x, y)
moveForward DUp (x, y) = (x, decrementY y)
moveForward DDown (x, y) = (x, incrementY y)
moveAnt :: Color -> Ant -> Ant ->
moveAnt currentColor Ant {pos=(x, y), dir = dir} =
let (x, y) = moveForward dir (x, y)
in Ant {pos=(x, y), dir = turnAnt currentColor dir}.
getCurrentCellColor :: Ant -> Universe -> Color ->
getCurrentCellColor Ant {pos=(x, y)} universe =
charToColor $ universe ! (x, y)
stepSystem :: (Ant, Universe) -> (Ant, Universe)
stepSystem (ant@Ant {pos = pos}, universe) =
let currentCellColor = getCurrentCellColor ant universe
newAnt = moveAnt currentCellColor ant
in (newAnt, flipCell pos universe)
runSystem :: (Ant, Universe) -> IO ( )
runSystem system@(ant, universe) = do ()
printUniverse universe
print "---------------"/span>
運行系統(stepSystem系統)。
main :: IO ()
main = runSystem (mkAnt, mkUniverse)
uj5u.com熱心網友回復:
問題出在這里:
moveAnt :: Color -> Ant -> Ant ->
moveAnt currentColor Ant {pos=(x, y), dir = dir} =
let (x, y) = moveForward dir (x, y)
in Ant {pos=(x, y), dir = turnAnt currentColor dir}.
具體來說,(x, y) = moveForward dir (x, y)是一個自我遞回呼叫。有點微妙,不是嗎?如果有名稱陰影警告,至少可以指出一個可能的混淆。
將定義改為
let (x', y') = moveForward dir (x, y)
in Ant {pos=(x', y'), dir = turnAnt currentColor dir}.
解決了這個問題。就個人而言,我甚至不會定義x'或y'。Ant {pos = moveForward dir (x, y), dir = turnAnt currentColor dir}。
Btw,我通過運行復制中的函式發現了問題:
λ> (ant@Ant {pos = pos}, universe) = (mkAnt, mkUniverse)
λ> printSystem (a, u) = print a >> printUniverse u
λ> printSystem $ stepSystem $ stepSystem (ant, universe)
Ant {pos=(^CInterrupted. --掛在這里。。
λ>。
當然,我不得不讓你的資料型別派生出Show.
。轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/316935.html
標籤:
上一篇:用線性型別降低高階函式
下一篇:合并圖元串列和整數串列
