[英]Altering A Single Value in List of Lists in Haskell [Homework]
对此存在一些实际问题,并且在任何阅读中都找不到有关此操作的任何指导。 负责执行功能以完成Connect 4的Haskell版本。该板使用Data.List表示为零件清单列表。
功能之一是给定件号和列号删除件。 为此,我只想将片段添加到适当的列中并完成它,但是我似乎能够做到的唯一方法是遍历列表,直到到达正确的列,然后添加片段。
有什么办法可以更好地做到这一点?
我的可怕代码如下:
cheatPiece :: GameState -> Int -> Piece -> GameState
cheatPiece [] _ _ = []
cheatPiece (xs:xss) 0 x = (x:xs) : xss
cheatPiece (xs:xss) n x = xs : cheatPiece xss (n-1) x
我认为您的实现一点都不可怕。 这几乎是处理不可变链表的标准方法。
我认为让自己感到笨拙的主要因素是,使用索引和链接列表永远不会很自然。
因此,在家庭作业分配的背景下,我认为您的实现是实现cheatPiece
的最正确方法。 如果您可以控制板子的演示文稿,我可能会考虑使用vector
或IntMap
来存储列。
总有一个lens
可以让您使用terser抽象来处理嵌套的,不变的结构,但是如果您还不熟悉Haskell,那么这个lens
包绝对不具备最柔和的学习曲线。
import Control.Lens
data Piece = X | O deriving Show
type GameState = [[Piece]]
cheatPiece :: GameState -> Int -> Piece -> GameState
cheatPiece st i p = st & ix i %~ (p:)
您可以使用take
drop
功能和列表索引运算符!!
。
cheatPiece xss n x = take n xss ++ [x : (xss !! i)] ++ drop (n + 1) xss
还是有将splitAt
和删除splitAt
的splitAt
当索引太大时,我将进行检查:
cheatPiece xss n x = case splitAt n xss of
(_, []) -> error "out of range"
(yss, zs:zss) -> yss ++ [x:zs] ++ zss
但是我很想通过编写一个用于修改索引元素的函数来概括一下这一点:
modifyAt :: Int -> (a -> a) -> [a] -> [a]
modifyAt n f xs = case splitAt n xs of
(_, []) -> error "out of range"
(ys, z:zs) -> ys ++ [f z] ++ zs
可以这样使用:
> modifyAt 3 (+1000) [0..9]
[0,1,2,1003,4,5,6,7,8,9]
然后你的功能是
cheatPiece xss n x = modifyAt n (x:) xss
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.