在Ncurses中使用IO

时间:2017-05-06 09:27:59

标签: haskell io ncurses

我正在尝试使用UI.NCurses

https://john-millikin.com/software/haskell-ncurses/reference/haskell-ncurses/latest/

进行一些简单的寻路课程 问题是我有一个随机的Int当然会返回一个IO Int 这意味着我有一个IO TerrianType,然后导致一个IO TerrianType数组

问题是我需要在main中解决这些问题,以便使用drawString将它们打印到屏幕上。我包括以下代码:

module Main where
  2   import UI.NCurses
  3   import Control.Monad
  4   import Control.Monad.IO.Class
  5   import System.Random
  6 
  7   -- Tutorials
  8   -- working on several path findng algorithims
  9   -- http://www.redblobgames.com/pathfinding/a-star/introduction.html
 10 
 11   -- | The 'Compass' data type provides breadcrumbs from the goal to the start. 
 12   data Compass = N | S | E | W deriving (Show, Eq)
 13 
 14   -- | 'Cartogram' is a structure of compass directions that mirrors the terrian.
 15   type Cartogram = [Compass]
 16 
 17   -- | 'TerrianType' determines how hard a cell is to traverse.
 18   data TerrianType = Sand | Forest | Goal deriving (Show, Eq)
 19 
 20   -- | 'Terrian' is a collection of TerrianTypes with a single goal.
 21   type Terrian = [IO TerrianType]
 22 
 23   -- | 'roll' gets a random int from 1 to the parameter
 24   roll :: Int -> IO Int
 25   roll m
 26     | m <= 0 = getStdRandom (randomR (1,1))
 27     | m > 0 = getStdRandom (randomR (1,m)) 
 28 
 29   -- | 'getRandomTerrian' gets a random TerrianType 
 30   getRandomTerrian :: IO TerrianType
 31   getRandomTerrian = do
 32     r <- roll 3
 33     case r of
 34       1 -> return Forest
 35       2 -> return Sand
 36       3 -> return Goal
 37       _ -> return Sand
 38 
 39   -- | 'constructTerrian' constructs a Terrian array of random TerrianTypes
 40   constructTerrian :: Int -> Int -> Terrian
 41   constructTerrian n1 n2 = take (n1 * n2) $ repeat getRandomTerrian
 42 
 43   drawShow a = (drawString . show) a
 44  
 45   --showString :: t -> String
 46   --showString t = show t
 47 
 48   main :: IO ()
 49   main = do
 50     runCurses $ do
 51       setEcho False
 52       w <- defaultWindow
 53       updateWindow w $ do
 54         moveCursor 1 1
 55         mapM drawShow (constructTerrian 5 5)
 56       render
 57       waitFor w (\ev -> ev == EventCharacter 'q' || ev == EventCharacter 'Q')58 
 59   waitFor :: Window -> (Event -> Bool) -> Curses ()
 60   waitFor w p = loop where
 61     loop = do
 62       ev <- getEvent w Nothing
 63       case ev of
 64         Nothing -> loop
 65         Just ev' -> if p ev' then return () else loop

 • No instance for (Show (IO TerrianType))
        arising from a use of ‘drawShow’
 • In the first argument of ‘mapM’, namely ‘drawShow’
      In a stmt of a 'do' block: mapM drawShow (constructTerrian 5 5)
      In the second argument of ‘($)’, namely
        ‘do { moveCursor 1 1;
              mapM drawShow (constructTerrian 5 5) }’

1 个答案:

答案 0 :(得分:1)

我认为您会混淆IO [TerrianType][IO TerrianType]

在您的代码中,您生成一个mapM,这是一个IO操作列表。当你TerrianType时,如果你想访问他们的drawShow :: (IO TerrianType) -> IO () drawShow a = a >>= drawString . show 并打印它们,你必须运行

所以,你可能需要像

这样的东西
[IO TerrianType]

但是,我确实想知道constructTerrian :: Int -> Int -> [IO TerrianType] 是否是正确的开始。而不是使用

constructTerrian :: Int -> Int -> IO [TerrianType]

正如您现在所做的那样,您可能应该转移到

{{1}}

并相应地更改代码。第一个代码不计算随机值,而只返回一个IO动作列表,它将滚动随机值。也许您现在想要滚动它们,并生成一个值列表,如第二种类型所暗示的那样。