我正在尝试使用以下代码编写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"中得到了解析错误。 ...
答案 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
此解决方案最初可能看起来不是很强大,但是当您开始尝试更新嵌套记录时,我向您保证优势会变得清晰。