现在,我对代码进行了一些改进,将其裁剪掉,等等。
这是源代码:

import Prelude


{-- DEFINE THE TYPES --}
data Tile = Tile  -- the tiles of the map
    {char :: Char
    ,isBlocking :: Bool
    ,position :: (Int,Int)}

type Dungeon = [Tile]  -- the dungeon


{-- THE MAIN FUNCTION --}
main :: IO ()
main = do
    let theDungeon :: Dungeon
        theDungeon = mkDungeon 0 0 []
    writeFile "./test.log" $ show theDungeon


{-- DEFINE THE SIZE OF THE MAP --}
screenX = 80
screenY = 24

mapX = screenX
mapY = screenY - 4

{-- THE FUNCTIONS FOR THE DUNGEON --}
mkDungeon :: Int -> Int -> Dungeon -> Dungeon -- function for generating the dungeon
mkDungeon x y dungeon =
    if x > mapX  -- looks if the line isn't too long
        then mkDungeon 0 (y + 1) dungeon  -- it's too long, so make the next line
        else if y == 0  -- if it at the top
            then mkDungeon (x + 1) y $ dungeon ++ [Tile '#' True (x, y)}
            else if y > 0 && y < mapY  -- looks if the line is in the middle
                then if x == 0 || x == mapX  -- is it at the right or at the left
                    then mkDungeon (x + 1) y $ dungeon ++ [Tile '#' True (x, y)]
                    else mkDungeon (x + 1) y $ dungeon ++ Tile '.' False (x, y)]
                else if y == mapX  -- looks if it is at the bottom
                    then do mkDungeon (x + 1) y  $ dungeon ++ [Tile '#' True (x, y)]
                    else return $ dungeon :: Dungeon

所以现在,当我尝试编译它时,我变成了这个错误:
main.hs:42:26:
    Couldn't match type ‘[Tile]’ with ‘Tile’
    Expected type: Dungeon
      Actual type: [Dungeon]
    In the expression: return $ dungeon :: Dungeon
    In the expression:
    ...

据我了解,它尝试返回列表的列表,但不会导致关闭:
mkDungeon :: Int -> Int -> Dungeon -> Dungeon

但是如果我写
else return $ dungeon

相反,我收到此错误:
main.hs:42:26:
    Couldn't match type ‘[Tile]’ with ‘Tile’
    Expected type: Dungeon
      Actual type: [Dungeon]
    In the expression: return $ dungeon
    ...

当我不使用$编写它时,我得到了:
main.hs:42:26:
    Couldn't match type ‘[Tile]’ with ‘Tile’
    Expected type: Tile
      Actual type: Dungeon
    In the expression: return dungeon
    ...

那么,如何将其作为Dungeon类型返回?

最佳答案

因此,另一个答案已经说明,您需要将let x = ...用作常规值,而仅将x <- ...用作单子(monad) Action 。这是您的问题之一。

您也不需要do中的所有这些mkDungeon块。而不是

then do
  dungeon : Tile '#' True (x,y)
  mkDungeon (x + 1) y

你想要类似的东西
then mkDungeon (x + 1) y (dungeon : Tile '#' True (x,y))

换句话说,将新的地牢传递给mkDungeon的递归调用。但是,当然,这是错误的方法:新的图块应位于(:)运算符的左侧,而不是右侧。
then mkDungeon (x + 1) y (Tile '#' True (x,y) : dungeon)

下一个问题是你有
data Dungeon = Dungeon [Tile]

这意味着如果xyzTile值,则
Dungeon [x, y, z]

Dungeon值,但是
[x, y, z]

本身不是。您的mkDungeon类型签名声称需要一个Dungeon并返回另一个Dungeon,但实际上,它似乎正在尝试获取一个 slice 列表并返回另一个 slice 列表。

有两种方法可以解决此问题。一种是使Dungeon成为纯类型别名,而不是全新的类型:
type Dungeon = [Tile]

现在Dungeon[Tile]是可互换的,一个仅仅是另一个的别名。或者,您需要在各处插入Dungeon:
mkDungeon x y (Dungeon ts) = ...
   ...then mkDungeon (x + y) y (Dungeon (Tile '#' True (x,y) : ts))
   ...

10-05 21:11