考虑以下
data Point=Point{x::Float,y::Float}
data Shape=Circle{centre::Point,radius::Float}
|Rectangle {uleft::Point,bRight::Point}
Run Code Online (Sandbox Code Playgroud)
这里的Shape类型是Circle和Rectangle两种类型的副产品.我可能想在其他地方重用Circle和Rectangle类型.所以这样做会很有用:
data Point=Point{x::Float,y::Float}
data Circle=Circle{centre::Point,radius::Float}
data Rectangle=Rectangle {uleft::Point,bRight::Point}
data Shape =Circle | Rectangle
Run Code Online (Sandbox Code Playgroud)
但是当我这样做时出现编译错误:Circle被声明两次.尝试这个的正确语法是什么,或者这不可能?
Ben*_*ood 14
Haskell中类型的副产品通常表示为Either:
data Either a b = Left a | Right b
type Shape = Either Circle Rectangle
-- so you have shapes as either Left c for some Circle c
-- or Right r for some Rectangle r
Run Code Online (Sandbox Code Playgroud)
这很好用,虽然由于技术原因,它不完全是副产品.另一种常见的方法是定义类似的类型:
data Shape = CircleShape Circle | RectangleShape Rectangle
Run Code Online (Sandbox Code Playgroud)
让CircleShape :: Circle -> Shape和RectangleShape :: Rectangle -> Shape是你的两个注射.
这是错误的说法,你在你的问题做原来Shape是一个类型的副产品Circle和Rectangle,因为后两者都没有的类型.如果你想设置的东西Circle p r既是类型的值又是类型Circle的值Shape,那么这实际上与Haskell类型系统的精神相反(尽管类似的系统扩展可能有类似的东西).
Pth*_*ame 10
这不是直接可行的,但您有几个选择.在这种情况下,我会用一个GADT索引DataKind:
{-# LANGUAGE DataKinds, GADTs, KindSignatures #-}
data ShapeType = Circle | Rectangle
data Shape :: ShapeType -> * where
CircleShape :: { centre :: Point, radius :: Float } -> Shape Circle
RectangleShape { uleft :: Point, bRight :: Point } -> Shape Rectangle
Run Code Online (Sandbox Code Playgroud)
然后,无论何时你想要处理一般的形状,你只需使用Shape a,如果你想要一个矩形或圆形,你可以分别使用Shape Rectangle或Shape Circle.
| 归档时间: |
|
| 查看次数: |
5054 次 |
| 最近记录: |