基本的Haskell函数

sok*_*ras 3 haskell

我是Haskell的新手,我正在努力学习基础知识.我需要声明一个名为Pos的类型,它将具有两个整数然后我需要方向北,南,西,东,以便我可以根据方向改变位置.一旦我这样做,我需要创建一个称为移动的函数,它将获取移动列表和初始位置,并在所有移动后返回位置.这是我的代码,但我仍然坚持我必须遍历移动列表.

type Pos = (Int, Int)
data Direction = North | South | East | West

move :: Direction -> Pos -> Pos
move North (x,y) = (x, y+1)
move West (x,y) = (x-1, y)
move South (x,y) = (x, y-1)
move East (x,y) = (x+1, y)

moves :: [Direction] -> Pos -> Pos
moves [] (x,y) = (x,y)
moves (h:xs) (x,y) 
        | h == North = move North (x,y)
        | h == West  = move West (x,y)
        | h == South = move South (x,y)
        | otherwise  = move East (x,y)
Run Code Online (Sandbox Code Playgroud)

我在这里错过了什么?

And*_*ewC 9

将一系列事物组合成一个东西称为折叠列表.有(大约)两个列表折叠:foldlfoldr.倾向于使用折叠是学习Haskell的重要一步.我们需要foldl,有类型

foldl :: (a -> b -> a) -> a -> [b] -> a
Run Code Online (Sandbox Code Playgroud)

现在foldl通过使用组合函数和初始值来组合列表中的东西,例如

foldl (£) s [x,y,z] = (((s £ x) £ y) £ z)
Run Code Online (Sandbox Code Playgroud)

(l输入foldl是左边的缩写,所以它可以帮助你记住你的起始值s将在左边结束,但更重要的是括号与左边相关联.)

第三个参数是list参数[b].我们将其用于移动列表,因此类型b将是Direction.

第二个参数是类型的起始值a,因此我们将使用它作为您的初始位置,因此类型a将是Pos.

第一个参数是将列表中的内容与当前值组合在一起的函数.现在我们知道的类型baDirectionPos我们知道,我们的组合函数的类型必须是Pos -> Direction -> Pos.移动函数几乎正是我们需要的,除了我们需要交换参数.该flip功能就是这样flip move,我们需要的类型也是如此.

因此,我们将专门的类型foldl

foldl :: (Pos -> Direction -> Pos) -> Pos -> [Direction] -> Pos
Run Code Online (Sandbox Code Playgroud)

并定义

moves :: [Direction] -> Pos -> Pos
moves ds i = foldl (flip move) i ds
Run Code Online (Sandbox Code Playgroud)

现在foldl有一个"严格"的版本foldl',在这种情况下更快,所以如果你在快节奏的游戏中使用它,或者处理大量的动作,你会想要使用那个.

与往常一样,您可以通过在hoogle上搜索其名称或类型来查找功能.

还有一个折叠功能,它以不同的方式折叠列表.您可以在这个问题中了解它们之间的区别.简而言之,foldr工作方式如下:

foldr (?) s [x,y,z] = (x ? (y ? (z ? s)))
Run Code Online (Sandbox Code Playgroud)

(rin foldr是对的缩写,所以它可以帮助你记住你的起始值s最终会在右边,但更重要的是括号与右边相关联.)

  • 很好的答案.我只是想指出,如果你重构使`move :: Pos - > Direction - > Pos`和`move :: Pos - > [Direction] - > Pos`,那么`moves`的实现会减少为` moves = foldl move`. (2认同)