在Haskell中更改记录值

时间:2016-06-28 20:43:35

标签: haskell record

我正在尝试使用以下代码编写Haskell模块:

module RectangleMover where

data Rectangle = Rectangle { xCoordinate :: Int
                           , yCoordinate :: Int
                           , width :: Int
                           , height :: Int
                           } deriving (Show)

move :: Rectangle -> Int -> Int -> Rectangle
-- Edit 1
move rec x y =
    let rec' = { xCoordinate + x
               , yCoordinate + y
               }
    return rec

要创建一个矩形,我会输入:

let rec = Rectangle 10 10 20 30

但我现在的问题是如何实现一个"移动"这个矩形? 在C#或Java中,调用将是这样的:rec.move(20,20); 但是如何在Haskell中编写呢?

不幸的是,我第一次尝试使用函数式编程语言......

编辑1: 我在我的函数中添加了代码,但仍然在" xCoordinate + x"中得到了解析错误。 ...

3 个答案:

答案 0 :(得分:6)

Haskell值是不可变的,因此您希望返回一个新的Rectangle,并修改了所需的属性。这很简单,使用“记录更新语法”,如let myNewRec = rec { yCoordinate = 20, xCoordinate = 20 }

答案 1 :(得分:6)

您只需将偏移添加到角落:

move :: Rectangle -> Int -> Int -> Rectangle
move (Rectangle x y w h) dx dy = Rectangle (x + dx) (y + dy) w h

但是,使用记录语法,您可以将其写为

move :: Rectangle -> Int -> Int -> Rectangle
move r@(Rectangle {xCoordinate = x, yCoordinate=y}) dx dy = r {
  xCoordinate = x + dx,
  yCoordinate = y + dy }

更长,但仅限于为两个字段选择的长名称进行更新。您可以进一步定义Point类型:

data Point = Point Int Int
movePoint :: Point -> Int -> Int -> Point
movePoint (Point x y) dx dy = Point (x + dx) (y + dy)

data Rectangle = Rectangle { corner :: Point, width :: Int, height :: Int }
move :: Rectangle -> Int -> Int -> Rectangle
move r@(Rectangle {corner=c}) dx dy = r { corner = movePoint c dx dy }

答案 2 :(得分:6)

鉴于这是你第一次使用Haskell,请使用已经提到的记录更新答案。但是,对于将来使用Google搜索的人,以及如果您感觉更有野心(或未来的学习),Haskell也有这个非常受欢迎且功能非常强大的库lens

以下是如何使用它来设计解决问题的方法。

{-# LANGUAGE TemplateHaskell #-}
import Control.Lens

data Rectangle = Rectangle { _xCoordinate :: Int
                           , _yCoordinate :: Int
                           , _width :: Int
                           , _height :: Int
                           } deriving (Show)
makeLenses ''Rectangle

move :: Rectangle -> Int -> Int -> Rectangle
move rect dx dy= rect
                   & xCoordinate +~ dx
                   & yCoordinate +~ dy

此解决方案最初可能看起来不是很强大,但是当您开始尝试更新嵌套记录时,我向您保证优势会变得清晰。