Haskell 的两级类型层次结构

Gab*_*ino 2 haskell types functional-programming

我想在我的应用程序中模拟 4 种方向:右、左、上和下。但是,我希望能够拥有一个函数,该函数只对变量使用水平函数,对其他变量使用垂直函数。

为了解决这个问题,我可以有两种类型:Horizo​​ntalDirection 和 VerticalDirection:

data HorizontalDirection = RightDir | LeftDir
data VerticalDirection = UpDir | DownDir

foo :: HorizontalDirection -> VerticalDirection -> String
foo hDir vDir = "This works" 
Run Code Online (Sandbox Code Playgroud)

但是,我也希望能够拥有一个可以采用一种类型和另一种类型的函数,如下所示:

bar :: Direction -> String
bar (HorizontalDirection _) = "Horizontal!"
bar (VerticalDirection _)   = "Vertical!"
Run Code Online (Sandbox Code Playgroud)

但这不起作用,因为 Horizo​​ntalDirection 和 VerticalDirection 不是数据构造函数。

我知道我可以使用任一个并使其工作,如下所示:

bar :: (Either HorizontalDirection VerticalDirection) -> String
bar (Left _) = "Horizontal!"
bar (Right _) = "Vertical!"
Run Code Online (Sandbox Code Playgroud)

但是,我想知道我是否可以在没有任何类型的情况下做到这一点。

我也尝试使用类型类:

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"
Run Code Online (Sandbox Code Playgroud)

但这给了我以下编译器错误:

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)
Run Code Online (Sandbox Code Playgroud)

我的思维方式在这里完全错误吗?或者我只是错过了什么?

Li-*_*Xia 8

Either您可以使用更有意义的名称声明新的数据类型,而不是使用。

data Direction
  = Horizontal HorizontalDirection
  | Vertical   VerticalDirection

bar :: Direction -> String
bar (Horizontal _) = "Horizontal!"
bar (Vertical _) = "Vertical!"
Run Code Online (Sandbox Code Playgroud)