0

ここで、コードを少し改善したり、何かを切り取ったりしました。
ソースコードは次のとおりです。

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

4 に答える 4

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が、実際の定義は含まれていないということです。次の問題は、モナドではない type の値を生成するmkDungeon 0 0 []ことです。Dungeon>>=<-

theDungeon適切に定義するには、=代わりに<-(<-はモナドから値を「抽出」するためのものであり>>=、を使用して脱糖され、 (およびグローバルな) バインディングに使用されます) を使用し、ブロックの一部であるような方法でインデントする必要があり=ます。そう:letlet

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

または、型シグネチャをスキップして、単に書くこともできますlet theDungeon = mkDungeon 0 0 []

于 2016-06-20T16:56:18.670 に答える
0

私はそれを解決しました。コード
でわかるように、次の ようにして解決しました。

... $ dungeon ++ [Tile ...]

皆さんもありがとう!それは大いに役立ちました:D.

于 2016-06-22T17:30:40.260 に答える
0

したがって、別の回答ではlet x = ...、通常の値に使用する必要がありx <- ...、モナドアクションにのみ使用する必要があるとすでに説明されています。それはあなたの問題の1つです。


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]

それ自体ではありません。あなたの型シグネチャは、 a をmkDungeon取り、Dungeonanother を返しますDungeonが、実際には、タイルのリストを取得して別のタイルのリストを返そうとしているようです。

これを修正するには 2 つの方法があります。Dungeon1 つは、まったく新しい型ではなく単なる型エイリアスを作成することです。

type Dungeon = [Tile]

NowDungeon[Tile]は互換性があり、一方は他方のエイリアスにすぎません。または、あちこちに挿入する必要がありますDungeon

mkDungeon x y (Dungeon ts) = ...
   ...then mkDungeon (x + y) y (Dungeon (Tile '#' True (x,y) : ts))
   ...
于 2016-06-21T09:17:20.273 に答える
0

mkDungeonの型シグネチャを持ちmkDungeon :: Int -> Int -> Dungeon -> Dungeon、 とDungeon同等であるため、[Tile]この関数はリストモナドに含まれています。

return使用しているモナドに値を持ち上げるモナド用に定義された関数です。 returnfor リストは次のように定義されます

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

したがって、dungeontypeDungeonを持っているので、それを渡すとreturnが得られます[dungeon]。これはあなたが望むものではなく、型シグネチャと一致しないため、エラーが発生します。

この場合、 return を使用する必要はまったくありません。これを削除すると、問題が解決するはずです。Haskell の return は、命令型言語の return とはまったく違うことを覚えておいてください。leave 関数は使用されません。

于 2016-06-21T21:10:36.803 に答える