【发布时间】:2020-03-28 11:36:57
【问题描述】:
我想在我的应用程序中为 4 种方向建模:右、左、上和下。但是,我希望能够有一个函数,该函数仅将水平变量用于变量,将垂直变量用于其他变量。
为了解决这个问题,我可以有两种类型:HorizontalDirection 和 VerticalDirection:
data HorizontalDirection = RightDir | LeftDir
data VerticalDirection = UpDir | DownDir
foo :: HorizontalDirection -> VerticalDirection -> String
foo hDir vDir = "This works"
但是,我也希望能够拥有一个可以采用一种类型以及另一种类型的函数,如下所示:
bar :: Direction -> String
bar (HorizontalDirection _) = "Horizontal!"
bar (VerticalDirection _) = "Vertical!"
但这不起作用,因为 HorizontalDirection 和 VerticalDirection 不是数据构造函数。
我知道我可以使用 Either 并使其工作,如下所示:
bar :: (Either HorizontalDirection VerticalDirection) -> String
bar (Left _) = "Horizontal!"
bar (Right _) = "Vertical!"
但是,我想知道我是否可以在没有 Either 类型的情况下做到这一点。
我也尝试过使用类型类:
data HorizontalDirection = RightDir | LeftDir
data VerticalDirection = UpDir | DownDir
class Direction a
instance Direction HorizontalDirection
instance Direction VerticalDirection
baz :: Direction d => d -> String
baz RightDir = "Horizontal"
但这给了我以下编译器错误:
Direction.hs:21:5: error:
• Couldn't match expected type ‘d’
with actual type ‘HorizontalDirection’
‘d’ is a rigid type variable bound by
the type signature for:
baz :: forall d. Direction d => d -> String
at Direction.hs:20:1-33
• In the pattern: RightDir
In an equation for ‘baz’: baz RightDir = "Horizontal"
• Relevant bindings include
baz :: d -> String (bound at Direction.hs:21:1)
我的思维方式在这里完全错误吗?还是我只是错过了什么?
【问题讨论】:
-
我不知道你反对在这里使用
Either是什么。如果只是构造函数的名称,您可以随时创建自己的 sum 类型,例如data Direction = Horizontal HorizontalDirection | Vertical VerticalDirection -
如果你喜欢冒险,你可以看看union types。
-
@RobinZigmond,这不是问题。我只是觉得这是错误的,因为我总是将 Either 视为一种错误处理方式。
标签: haskell types functional-programming