0

我一直在努力在 Haskell 中构建自己的外交模拟器来弄湿我的脚。

我相信我已经对什么是订单提出了一个不错的定义:

data Order = Hold Unit Territory
           | Move Unit Territory Territory
           | Support Unit Territory Unit Territory Territory
           | Convoy Fleet Territory Army Territory Territory
  deriving (Eq, Show)

对于那些不熟悉游戏的人,命令以“保持伦敦舰队”、“移动伦敦英吉利海峡舰队”、“支援英吉利海峡舰队北大西洋中大西洋舰队”或“护航舰队英吉利海峡军队”的形式写成伦敦布雷斯特”等。

现在,将 Unit 定义为data Unit = Fleet | Army (deriving Eq, Show),我得到了Not in scope: type constructor or class 'Fleet'关于 Order 定义的错误。

为什么是这样?

我应该如何编写单位或命令的定义(或者我应该做一些不同的事情),以允许我要求 Convoy 的第一个参数是舰队,第三个参数是陆军?

我对这个问题的处理方法“甚至没有错”吗?

我是否应该在我的验证功能中处理这个问题(因为据我所知,没有办法通过 Haskell 仅指定有效订单。它具有表现力但不具有表现力)?

我已经尝试过使用“DataKinds”,但这对我没有任何帮助(尽管错误后记建议这样做,但 Haskell 错误后记再次提出了很多建议,所以我怀疑我需要过多注意它)。

4

1 回答 1

4
data Unit = Fleet | Army 

Unit是一种类型。它的值可以是Fleet或者Army——这些不是类型。

data Order = Hold Unit Territory
           | Move Unit Territory Territory
           | Support Unit Territory Unit Territory Territory
                     ^^^^           ^^^^

这些是类型——好的。

           | Convoy Fleet Territory Army Territory Territory
                    ^^^^^           ^^^^

这些是价值观——不行。上面的行与

           | Convoy "hello" Territory 42 Territory Territory

这没有任何意义。

您可能只是想使用

           | Convoy Territory Territory Territory

但我对游戏不熟悉,所以我不知道你在那里真正需要什么。

另外,忘记类型类和DataKinds扩展——除非你真的需要,否则不要使用高级的东西。


作为另一种选择,如果您确实打算将字段添加到Fleetand Army,则将它们转换为类型

data Fleet = F String Int -- dummy fields, you can put none
data Army = A
data Unit = FleetUnit Fleet | ArmyUnit Army    -- added the types here
data Order = Hold Unit Territory
           | Move Unit Territory Territory
           | Support Unit Territory Unit Territory Territory
           | Convoy Fleet Territory Army Territory Territory

现在最后一行没问题。这样做的代价是您需要使用更多“包装”构造函数来构建订单,例如

orderExample1 :: Order
orderExample1 = Convoy (F "test" 33) terr1 A terr2 terr3

orderExample2 :: Order
orderExample2 = Support (FleetUnit (F "test2" 55)) terr1 (ArmyUnit A) terr2 terr3

上面,F ...构建 a Fleet,然后FleetUnit ...将其转换为Unit,最后Support ...将其转换为Order

于 2016-08-01T08:40:32.327 回答