我有一个函数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
的建议?
答案 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_con
是Int -> 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
,多态性也可以让你对你的类型更具描述性。