我定义了两种数据类型:Point和Curve.Point的坐标有两个双精度,曲线有一个起点和一个表示曲线其余部分的点列表.我需要创建一个函数来创建这个曲线给定一个起点和一个点列表,但我不太明白我应该如何在曲线内的点列表中添加一个元素.这是我的代码:
data Point = Point Double Double deriving (Eq, Show)
point :: (Double, Double) -> Point
point (x, y) = Point x y
data Curve = Curve Point [Point] deriving (Eq, Show)
curve :: Point -> [Point] -> Curve
curve x [] = Curve x []
curve x [y] = Curve x [y]
curve x (y:ys) = curve x (y:ys)
Run Code Online (Sandbox Code Playgroud)
我很确定我的递归最终是错误的.那么你能给我一些关于如何在列表中添加一个点的指南吗?
谢谢
Run Code Online (Sandbox Code Playgroud)myCurve = Curve (Point 2 2) [Point 3 3, Point 4 4, Point 5 5]
等等,你说什么?的确,Curve已经是你想要的功能了.它既是类型构造函数(数据定义中的左侧),也是值构造函数(右侧).
如果你Curve用ghci 探测,你会发现......
Run Code Online (Sandbox Code Playgroud)Prelude> :t Curve Curve :: Point -> [Point] -> Curve
同样的道理Point.换句话说,您的整个代码如下所示:
Run Code Online (Sandbox Code Playgroud)data Point = Point Double Double deriving (Eq, Show) data Curve = Point [Point] deriving (Eq, Show)
编辑:价值构造者的超小型入门.
创建新数据类型时,将自动创建值构造函数,该构造函数是一个创建新类型值的函数.在您的示例中并不完全清楚,因为类型和值构造函数具有相同的名称,这在Haskell中是允许的,因为一个存在于类型级别而另一个存在于值级别中.让我们试着让它更明显一点:
data MyIntType = MakeIntType Int
Run Code Online (Sandbox Code Playgroud)
现在,MakeIntType是一个函数,它接受一个参数,一个Int,并创建一个类型的值MyIntType.我们在ghci中检查一下:
Prelude> :t MakeIntType
MakeIntType :: Int -> MyIntType
Run Code Online (Sandbox Code Playgroud)
现在,我们可以编写一个相同的函数,就像你提出的那样:
makeIntType :: Int -> MyIntType
makeIntType x = MakeIntType x
Run Code Online (Sandbox Code Playgroud)
或者,删除显式点(参数):
makeIntType = MakeIntType
Run Code Online (Sandbox Code Playgroud)
这两个等式都表明我们已经重复了工作.makeIntType和MakeIntType之间没有功能差异.它们是完全等价的,因为你总是"免费"获得值构造函数,所以makeIntType是已经存在的东西的完全多余的别名.
我希望稍微澄清一下.
编辑2:Curve基于现有修改创建新修改
addPointToStartOfCurve p (Curve p' ps) = Curve p (p':ps)
Run Code Online (Sandbox Code Playgroud)
在这里,我们通过将现有曲线的第一个元素推到点列表并添加新的起点来从现有曲线创建新曲线.另一种变体会在现有曲线的末尾添加一个点.
addPointToEndOfCurve p (Curve p' ps) = Curve p' (ps ++ [p])
Run Code Online (Sandbox Code Playgroud)
请注意,由于不变性,原始曲线不会改变,我们只是生成新值.