我想在应用程序中对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!"
但是,我想知道是否可以在没有这两种类型的情况下做到这一点。
我也尝试使用类型类:
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)
我的思维方式在这里完全错误吗?还是我只是想念什么?
答案 0 :(得分:8)
您可以使用更有意义的名称声明新的数据类型,而不用使用Either
。
data Direction
= Horizontal HorizontalDirection
| Vertical VerticalDirection
bar :: Direction -> String
bar (Horizontal _) = "Horizontal!"
bar (Vertical _) = "Vertical!"
答案 1 :(得分:3)
您非常接近,但您需要在类中将函数定义为:
class Direction a where
baz :: a -> String
instance Direction HorizontalDirection where
baz _ = "Horizontal"
instance Direction VerticalDirection where
baz _ = "Vertical"
但是请注意,Haskell是静态类型的,并且类型在编译时是已知的。