[英]Haskell cannot get right type from ':' cons operator
我在嘗試使用深度優先搜索算法中的地圖來測試路徑以將目標單元包含在無方向且無循環的迷宮中時遇到錯誤。 我遇到麻煩的地方是map的遞歸調用。
這是我的代碼:
type Maze = [[Cell]]
data Cell = Cell { top, left, right, bottom :: Bool }
type Pos = (Int, Int)
type Path = [Pos]
findPath :: Maze -> Path
findPath [] = []
findPath maze = dfs maze [] (-1,-1) (1,1)
dfs :: Maze ->Path -> Pos -> Pos -> Path
dfs maze trail prev curr
| (curr == goal) = reverse $ goal : trail -- ?
| (null adj) = []
| otherwise = dfs maze (curr : trail) curr `map` (adj c (fst curr) (snd curr) prev)
where c = maze!!(fst curr- 1)!!(snd curr - 1)
goal = (length maze, length (maze!!0))
adj:: Cell -> Int -> Int -> Pos ->Path
adj c x y prev = if (top c && prev /= (x-1, y)) then [(x-1, y)] else [] ++
if (left c && prev /= (x, y-1)) then [(x, y-1)] else [] ++
if (right c && prev /= (x, y+1)) then [(x, y+1)] else [] ++
if (bottom c && prev /= (x+1, y)) then [(x+1, y)] else []
我對dfs maze (curr : trail) curr 'map' (adj c (fst curr) (snd curr) prev)
期望是我將函數f::Pos->trail
應用於[Pos]
每個元素,但是(curr : trail)
給出的是[Path]
而不是Path
錯誤堆棧給我如下:
stack: WARNING! Expecting stack options comment at line 1, column 1
stack: WARNING! Missing or unusable stack options specification
stack: WARNING! Using runghc without any additional stack options
SolveMaze.hs:77:24: error:
* Couldn't match type `[Pos]' with `(Int, Int)'
Expected type: Path
Actual type: [Path]
* In the expression:
dfs maze (curr : trail) curr
`map` (adj c (fst curr) (snd curr) prev)
In an equation for `dfs':
dfs maze trail prev curr
| (curr == goal) = reverse $ goal : trail
| (null adj) = []
| otherwise
= dfs maze (curr : trail) curr
`map` (adj c (fst curr) (snd curr) prev)
where
c = maze !! (fst curr - 1) !! (snd curr - 1)
goal = (length maze, length (maze !! 0))
|
77 | | otherwise = dfs maze (curr : trail) curr `map` (adj c (fst curr)
(snd curr) prev)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^
很抱歉,如果這對於您的Haskell向導來說確實是一個基本問題,但是我一直盯着這個問題已經很長時間了,以至於我無法接受它,需要伸出援助之手。 謝謝。
讓我們放大兩行。 首先是dfs的類型:
dfs :: Maze ->Path -> Pos -> Pos -> Path
因此,完全應用后的dfs會返回Path
,很好。
我們還有dfs的定義,它必須返回一個Path,它是:
dfs maze (curr : trail) curr `map` (adj c (fst curr) (snd curr) prev)
或通過一些簡化來明確說明正在發生的事情:
map (dfs and some args) (some list)
因此,dfs必須返回路徑,即類型,但定義將其顯示為返回路徑列表。
您似乎想要的是嘗試下降到相鄰位置之一並執行深度優先搜索,然后下降到下一條可能的路徑,並利用沿途的惰性評估-太好了!
讓我們將dfs更改為返回路徑列表( [Path]
)-如果發現死角,它將是解決方案或非解決方案的列表( []
)。 將reverse ...
更改為[reverse ...]
。 並map
到concatMap
。
詢問函數是否為null沒有意義,我認為您提到過adj
的應用,例如null (adj c (fst curr) ...
現在,查找路徑必須選擇dfs現在返回的解決方案列表之一-第一個就足夠了。 您可以使用listToMaybe
來獲取Maybe Path
結果。
。
import Data.Maybe (listToMaybe)
type Maze = [[Cell]]
data Cell = Cell { top, left, right, bottom :: Bool }
type Pos = (Int, Int)
type Path = [Pos]
findPath :: Maze -> Maybe Path
findPath [] = Just []
findPath maze = listToMaybe $ dfs maze [] (-1,-1) (1,1)
dfs :: Maze ->Path -> Pos -> Pos -> [Path]
dfs maze trail prev curr
| (curr == goal) = [reverse $ goal : trail] -- ?
| (null adjVal) = []
| otherwise = dfs maze (curr : trail) curr `concatMap` adjVal
where c = maze!!(fst curr- 1)!!(snd curr - 1)
goal = (length maze, length (maze!!0))
adjVal = adj c (fst curr) (snd curr) prev
adj:: Cell -> Int -> Int -> Pos ->Path
adj c x y prev = if (top c && prev /= (x-1, y)) then [(x-1, y)] else [] ++
if (left c && prev /= (x, y-1)) then [(x, y-1)] else [] ++
if (right c && prev /= (x, y+1)) then [(x, y+1)] else [] ++
if (bottom c && prev /= (x+1, y)) then [(x+1, y)] else []
如果您願意,還有很多其他事情可以清除。
[]
表示失敗的路徑,而不是Maybe Path
。 如果第一次深度優先搜索失敗,則您返回的“解決方案”將為[]
。 !!
並假設輸入沒有鋸齒。 您可以使用數組。 adj
詳細定義,可以使用警衛代替。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.