Haskell函数和映射

时间:2013-05-03 20:28:47

标签: function haskell map

这是一项家庭作业,我真的在最后一点苦苦挣扎。我们正在Haskell写“战舰”,除了一些关于功能语言的一般讲座之外,我们没有太多可继续的事情。没有教科书等。我已经被提到了几次LYAH,那里有很好的东西,但它似乎没有针对这个特定问题的建议。

对于上下文,我会将我的整个Battleship代码放上,这样你就可以看到我后来引用的定义。

--A
data Row = A | B | C | D | E | F | G | H | I | J deriving (Enum, Ord, Show, Bounded, Eq, Read)
data Column = One | Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten  deriving (Enum, Ord, Show, Bounded, Eq, Read)
--B
data Address = Address Row Column deriving (Show, Read, Eq)
--C
data Cell = Cell Address Bool deriving (Show, Read, Eq)
--D
data Ship = Ship [Cell] deriving (Show, Eq)
--E
data Ships = Ships [Ship] deriving (Show, Eq)
--F
toAddress r c = Address (toEnum r) (toEnum c)
--G
toRowColumn (Address aRow aColumn) = (fromEnum aRow, fromEnum aColumn)
--H
allAddressesA = [ Address row column | row <- [A .. J], column <- [One .. Ten]]
--I
allAddressesB = [toAddress row column | row <- [0 .. 9], column <- [0 .. 9]]
--J
targetShip (Ship ship) (Address row column)
  | Address == map (\list -> (head Address Bool)) s
--K
targetShips [(Ships)] toAddress //TODO
--L
isSunk Ship ship
  |ship [] = true
  |otherwise foldl 
--M
areSunk [(Ships)] //TODO

现在我也会发布具体的作业说明,以便在我需要帮助时没有任何沟通错误:

  

(j)编写接受Ship和目标的函数targetShip   地址作为其两个参数。如果船上有一个带目标的单元格   地址,该单元格被标记为沉没。这艘船的更新版本是   回。如果船舶为空,则返回空船。 (1张地图,   116个字符)

     

(k)编写接受列表的函数targetShips   船舶和目标地址作为其两个参数。它试图   将每艘船沉入船舶清单。它返回更新船只的清单。   如果没有船只,则返回空列表。 (1幅地图,86   人物)

     

(l)编写一个接受Ship作为其的函数isSunk   参数。如果船是空船,则返回true。除此以外,   如果所有单元格都标记为沉没,则返回true。 (1折,78个字符)

     

(m)写一个函数areSunk接受一个Ships列表作为它   参数。如果没有船只,则返回true。否则,返回   如果所有船舶都标记为沉没,则为true。 (1折,78个字符)

所以我在这里特别努力的是这些最后的4.解决方案(A - I)我已经测试过,它们的工作正常。

对于初学者,我们需要知道如何引用单元格值...分别为Address和Bool。

我们不能写更多功能。

我会假设你需要更多关于特定问题的解释,所以我会密切关注。任何有关最后四个问题从哪里开始的提示将不胜感激。提前谢谢你...我现在将回到我的文本编辑器,并试图解决这个问题。

2 个答案:

答案 0 :(得分:3)

  

(j)编写一个函数targetShip,它接受Ship和目标地址作为其两个参数。如果船上有一个具有目标地址的单元格,则该单元格被标记为沉没。返回船的更新版本。如果船舶为空,则返回空船。 (1张地图,116个字符)

功能targetShip
参数Ship and a target address as its two parameters
产生Ship is returned

这些信息足以记下您的函数的类型注释。

targetShip :: Ship -> Address -> Ship
targetShip (Ship ship) (Address row column) 

If the ship is empty, the empty Ship is returned
并且船只是列表或列表是空列表[]或带有尾部的头部,然后

targetShip :: Ship -> Address -> Ship
targetShip (Ship []) (Address row column) = Ship []
targetShip (Ship (x:xs)) (Address row column) = 

现在是困难的部分 If the ship has a cell with the target address, that cell is marked sunk
船是一个单元格列表,然后我需要为每个单元格(定义船只)检查当前单元格的地址是否与函数参数提供的地址相同。
好的,让我们的模式匹配出现的头x

targetShip :: Ship -> Address -> Ship
targetShip (Ship []) (Address row column)     = Ship []
targetShip (Ship (x:xs)) (Address row column) = 
    if x ... 
OMG,我做不到,因为没有帮助功能,我需要更多信息。我需要将x的结构出现在我的模式匹配中,就像这样,

targetShip (Ship ((Cell address bool):xs)) (Address row column) = 
再一次,OMG,我不能做更多,好的重做同样的事情,在我的模式匹配中更具表现力。

targetShip (Ship ((Cell (Address shipRow shipColumn) bool):xs)) (Address row column) = 

现在可以,我可以做到 我会让你完成它。

祝你好运

答案 1 :(得分:1)

J:你必须退回一艘船,船上有一个取决于地址的新清单。

targetShip (Ship oldCells) address = Ship newCells
  where newCells = ...
        f cell =

你如何找出新细胞?该任务建议使用地图。因此,您可以将函数f映射到oldCellsf应该做什么?如果它获得的地址与targetShip的参数具有相同的地址,则它应返回具有相同地址但具有凹陷状态的新单元格。否则它应该只返回作为参数给出的单元格。

K:一旦你获得目标工作,应该很容易。按照建议使用map

L和J:非常相似。任务建议使用折叠。你以前尝试过折叠吗?有两种基本类型,foldrfoldl,它们都通过采用带有两个参数的函数,累加器和当前元素,并将列表一次折叠到累加器中,使用给定的累加器。让我向您展示一些实际的折叠示例。

foldl (\acc x -> acc + x) 0 [1,2,3] -> 6 -- starting accumulator of 0
foldl (+) 0 [1,2,3] -> 6 -- same thing as above
foldl (&&) True [True, True, True] -> True -- folding booleans
foldl (&&) True [True, False, True] -> False -- more boolean folding
foldl (&&) True [] -> True -- folding an empty list yields the initial accumulator
foldl (\acc x -> acc && (x > 5)) True [6,7,8] -> True -- complex folding function.

使用最后一个函数,我希望你能看到,如何解决问题L和J.否则看看匿名函数中的模式匹配,并查看LYAH中的folding