函数的模式匹配

时间:2013-03-15 18:44:20

标签: haskell functional-programming pattern-matching

我有一个函数dir_con :: (Int -> Dir)

我想模式匹配以找到哪个特定的构造函数dir_con。数据类型为:

data Dir = Define Int
         | Equals Int 
         | Data Int  
         | LCset Int
         | NoArg Int

所以,dir_con将是Define,Equals等。它被传递给一个函数,我想像这样模式匹配:

case dir_con of
    NoArg -> Do something specific
    _     -> Do something for the rest

编译器不喜欢这样。错误消息为Couldn't match expected type 'Int -> Dir' with actual type 'Dir'

当然NoArg(Int -> Dir)类型的构造函数? Haskell不允许这种类型的模式匹配吗?我必须这样做,因为Dir构造函数来自地图。是否有关于如何以不同方式对待NoArg的建议?

3 个答案:

答案 0 :(得分:5)

两种方式:

case dir_con of
    NoArg _ -> Do something specific
    _     -> Do something for the rest

您正在匹配/ value /而不是构造函数。

或者,使用者记录语法:

case dir_con of
    NoArg {} -> Do something specific
    _     -> Do something for the rest

这是良好的卫生习惯,因为它在田间数量方面是中性的。

答案 1 :(得分:4)

您无法在功能上进行模式匹配。类型Dir的值是通过应用多个构造函数之一构建的,但dir_conInt -> Dir类型的函数。

您可能希望在模式匹配之前应用该功能:

case dir_con 7 of  -- `7` is just an arbitrary value I'm passing
  NoArg _ -> ...
  _       -> ...

此外,您还必须匹配NoArg构造函数的参数,否则在将参数添加到dir_con后您将收到另一个类型错误。

在你的具体情况中,你很可能不想传递一个文字整数,但也许是你从其他地方得到的一个参数:

myfun n = ... case dir_con n of
                NoArg _ -> ...
                _       -> ...

答案 2 :(得分:1)

如果你的所有构造函数都是Int -> Dir类型,那么我建议和@hammar一样:使构造函数类型为枚举:

data DirType = Define | Equals | Data | LCset | NoArg

data Dir = Dir DirType Int

然后你可以重构任何需要知道在那里使用值为DirType的构造函数。

尝试确定构造函数dir_con :: Int -> Dir的基本问题是,该类型的所有内容都不是构造函数。例如:

dispatch :: Int -> Dir
dispatch 0 = Define 0
dispatch 1 = Equals 1
dispatch n = NoArg n

对于“哪个构造函数”dispatch,您无法获得良好的答案。

如果Dir是参数

data Dir a = Define a | Equals a | Data a | LCset a | NoArg a

然后有一种Dir构造函数;即forall a. a -> Dir a(您需要{-# LANGUAGE RankNTypes #-}扩展名才能使用此类型)。这种类型不允许像dispatch那样检查其论点的诡计。所以如果你有:

dir_con :: forall a. a -> Dir a

然后你可以通过传递一个微不足道的值来检查它的构造函数

case dir_con () of
    ...

即使你只是几乎使用Dir Int,多态性也可以让你对你的类型更具描述性。