gpt4 book ai didi

haskell - 在我的 Haskell 代码中找不到错误

转载 作者:行者123 更新时间:2023-12-02 15:33:10 25 4
gpt4 key购买 nike

我尝试将卷心菜-山羊-狼难题的(有效!)解决方案从 Scala 转换为 Haskell,但在 findSolutions 中调用 head 时,代码抛出错误并出错> 因为解决方案列表是空的,所以问题似乎出在循环中的某个地方。 findMoves 似乎工作正常。

import Data.Maybe(fromMaybe)

data Item = Farmer | Cabbage | Goat | Wolf deriving (Eq, Show)

type Position = ([Item], [Item])

validPos :: Position -> Bool
validPos p = valid (fst p) && valid (snd p) where
valid list = elem Farmer list || notElem Goat list ||
(notElem Cabbage list && notElem Wolf list)

findMoves :: Position -> [Position]
findMoves (left,right) = filter validPos moves where
moves | elem Farmer left = map (\item -> (delItem item left, addItem item right)) left
| otherwise = map (\item -> (addItem item left, delItem item right)) right
delItem item = filter (\i -> notElem i [item, Farmer])
addItem Farmer list = Farmer:list
addItem item list = Farmer:item:list

findSolution :: Position -> Position -> [Position]
findSolution from to = head $ loop [[from]] where
loop pps = do
(p:ps) <- pps
let moves = filter (\x -> notElem x (p:ps)) $ findMoves p
if elem to moves then return $ reverse (to:p:ps)
else loop $ map (:p:ps) moves

solve :: [Position]
solve = let all = [Farmer, Cabbage, Goat, Wolf]
in findSolution (all,[]) ([],all)

当然,我也希望得到有关与实际错误无关的改进的提示。

[更新]

仅供记录,我按照建议使用Set。这是工作代码:

import Data.Set

data Item = Farmer | Cabbage | Goat | Wolf deriving (Eq, Ord, Show)

type Position = (Set Item, Set Item)

validPos :: Position -> Bool
validPos p = valid (fst p) && valid (snd p) where
valid set = or [Farmer `member` set, Goat `notMember` set,
Cabbage `notMember` set && Wolf `notMember` set]

findMoves :: Position -> [Position]
findMoves (left,right) = elems $ Data.Set.filter validPos moves where
moves | Farmer `member` left = Data.Set.map (move delItem addItem) left
| otherwise = Data.Set.map (move addItem delItem) right
move f1 f2 item = (f1 item left, f2 item right)
delItem item = delete Farmer . delete item
addItem item = insert Farmer . insert item

findSolution :: Position -> Position -> [Position]
findSolution from to = head $ loop [[from]] where
loop pps = do
ps <- pps
let moves = Prelude.filter (\x -> notElem x ps) $ findMoves $ head ps
if to `elem` moves then return $ reverse $ to:ps
else loop $ fmap (:ps) moves

solve :: [Position]
solve = let all = fromList [Farmer, Cabbage, Goat, Wolf]
in findSolution (all, empty) (empty, all)

findSolution 中对 head 的调用可以变得更安全,并且应该使用更好的方法来打印解决方案,但除此之外我很高兴有了它。

[更新2]

我认为之前的立场表述对于此类问题并不是最优的。我切换到以下数据模型,这使得 moving 等稍微更冗长,但更具可读性:

data Place = Here | There deriving (Eq, Show)

data Pos = Pos { cabbage :: Place
, goat :: Place
, wolf :: Place
, farmer :: Place
} deriving (Eq, Show)

最佳答案

问题是 [Farmer,Goat,Cabbage,Wolf][Farmer,Cabbage,Goat,Wolf] 不同,并且您不检查当使用 elemnotElem 时。一种解决方案是始终对元素列表进行排序,例如在函数 findMoves 中,您可以使用:

import Data.List(ord)
import Control.Arrow((***))

data Item = Farmer | Cabbage | Goat | Wolf deriving (Eq, Show, Ord)

findMoves (left,right) = map (sort***sort) $ filter validPos moves where
-- ....

solve = let all = sort [Farmer, Cabbage, Goat, Wolf]
-- ....

或者您可以使用一组 Item 而不是 Item 列表。

关于haskell - 在我的 Haskell 代码中找不到错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6580208/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com