我尝试返回列表时出错

时间:2016-06-20 16:46:33

标签: haskell compiler-errors roguelike

现在我改进了代码,削减了一些东西,等等 这是源代码:

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类型返回?

4 个答案:

答案 0 :(得分:2)

main = do
    let theDungeon :: Dungeon 
    theDungeon <- mkDungeon 0 0 []
    writeFile "./test.log" $ show theDungeon

如果我们从中删除语法糖,我们得到:

main =
    let
        theDungeon :: Dungeon
    in
        mkDungeon 0 0 [] >>= \theDungeon ->
        writeFile "./test.log" $ show theDungeon

错误消息抱怨的是let块包含theDungeon的类型签名,但没有实际定义。下一个问题是mkDungeon 0 0 []会生成Dungeon类型的值,而不是monad,因此您无法使用>>=(并且可以使用<-用它。

要正确定义theDungeon,您需要使用=代替<-<-用于&#34;从monad中提取&#34;值&#39}使用>>=进行desugared,=用于let(和全局)绑定)并将其缩进,使其仍然是let的一部分阻止。所以:

main = do
    let theDungeon :: Dungeon 
        theDungeon = mkDungeon 0 0 []
    writeFile "./test.log" $ show theDungeon

或者您可以跳过类型签名,只需编写let theDungeon = mkDungeon 0 0 []

答案 1 :(得分:0)

所以另一个答案已经解释过你需要使用let x = ...作为正常值,并且只使用x <- ...进行monadic动作。这就是你的一个问题。

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

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

你想要像

这样的东西
then mkDungeon (x + 1) y (dungeon : Tile '#' True (x,y))

换句话说,传递新地牢到递归调用mkDungeon。但当然,这是错误的方式:新的磁贴应该是(:)运算符的 left ,而不是右边。

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,但实际上它似乎正在尝试获取切片列表并返回另一个切片列表。

有两种方法可以解决这个问题。一种是使Dungeon仅仅是一种类型别名而不是一种全新的类型:

type Dungeon = [Tile]

现在Dungeon[Tile]可以互换,只是另一个的别名。或者,您需要在所有地方插入Dungeon

mkDungeon x y (Dungeon ts) = ...
   ...then mkDungeon (x + y) y (Dungeon (Tile '#' True (x,y) : ts))
   ...

答案 2 :(得分:0)

由于mkDungeon的类型签名为mkDungeon :: Int -> Int -> Dungeon -> Dungeon,而Dungeon[Tile]相同,因此此函数位于列表monad中。

return是为monad定义的函数,它将值提升为您正在使用的monad。列表的return定义为

return :: a -> [a]
return x = [x]

因为dungeon的类型为Dungeon,所以当您将其传递给return时,您会获得[dungeon]。这不是您想要的,并且与类型签名不匹配,这就是您收到错误的原因。

在这种情况下你根本不需要使用返回,删除它应该可以解决你的问题。请记住,Haskell中的返回与命令式语言中的返回完全不同;它不用于休假功能。

答案 3 :(得分:0)

我解决了它。
正如您在code中看到的那样 我通过制作:

解决了这个问题
nullptr

非常感谢大家!它帮助很大:D。