类型/种类在代数数据类型中的Haskell(可能)中的混淆

时间:2016-08-01 08:31:07

标签: haskell types algebraic-data-types data-kinds

我一直在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错误后记表明了很多事情,所以我怀疑我需要多注意它)。

1 个答案:

答案 0 :(得分:4)

data Unit = Fleet | Army 

Unit是一种类型。其值可以是FleetArmy - 这些不是类型。

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扩展名 - 不要使用高级内容,除非你真的需要它。

另一种选择是,如果您计划向FleetArmy添加字段,则将其转换为类型

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