我一直在Haskell建立自己的Diplomacy模拟器,让我的脚湿透。
我相信我已经为订单提出了一个不错的定义:
data Order = Hold Unit Territory
| Move Unit Territory Territory
| Support Unit Territory Unit Territory Territory
| Convoy Fleet Territory Army Territory Territory
deriving (Eq, Show)
对于那些不熟悉游戏的人来说,订单是以#34; Hold Fleet London",#34; Move Fleet London English Channel","支持舰队英语的形式写的。海峡舰队北大西洋中大西洋海域"或者" Convoy Fleet English Channel Army London Brest"等
现在,如果将单位定义为data Unit = Fleet | Army (deriving Eq, Show)
,我就订单的定义收到错误Not in scope: type constructor or class 'Fleet'
。
为什么会这样?
我怎样才能写出我对单位或订单的定义(或者我应该做些不同的事情),这使我能够要求康宏的第一个论点是舰队而第三个论点是陆军?
我只是"甚至不错"用我解决这个问题的方法?
我是否应该在我的验证功能中处理这个问题(因为据我所知,目前还没有通过Haskell指定有效订单的方法。它具有表现力但不具有表现力)?
我已经尝试使用" DataKinds",但这根本没有帮助我(尽管后记提示这样做的错误,然后再次,Haskell错误后记表明了很多事情,所以我怀疑我需要多注意它)。
答案 0 :(得分: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
扩展名 - 不要使用高级内容,除非你真的需要它。
另一种选择是,如果您计划向Fleet
和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 ...
构建Fleet
,然后FleetUnit ...
将其转换为Unit
,最后Support ...
将其转换为Order