如何解决确定数据类型实例的构造函数
我已经将自己编码到一个角落了吗?我的数据类型接近程序的入口点
data Token = A String | B String deriving (Eq,Show,Read)
在图书馆模块中,我有
type Constructor token = String -> token
回到入口点,我有类似的东西
constructor :: Constructor Token
constructor = A
tokenA :: Token
tokenA = A "a"
tokenB :: Token
tokenB = B "b"
在入口点和库之间的中间位置,我想使用的是
tokenUsesConstructor :: Constructor token -> token -> Bool
,以便可以对A
执行某些操作,而可以对B
执行不同的操作。以下内容对c无效,因为参数不能重复:
tokenUsesConstructor constructor (constructor _) = True
tokenUsesConstructor constructor (_ _) = False
-- use.hs:21:35: error: Parse error in pattern: constructor
,并且如错误所示(指示上述两行的第一行),问题比这更根本,正如
所示tokenUsesConstructor constructor token =
case token of
constructor _ -> True
_ -> False
会出现相同的错误(我认为前者只是后者的一个加糖版本)。如果我可以得到字符串,则可以进行构造和比较,但这实际上是关于匹配的相同问题。
是否可以在不进行模式匹配的情况下解构数据类型的实例?我不想在数据定义中添加更多内容或将其转换为记录类型。
(顺便说一句,我已经通过在构造函数中创建一个任意标记,显示了原始术语和构造的术语,然后比较了单词的开头来解决了这个问题,但这似乎是一种解决方法。)
解决方法
模式的构造器部分必须是静态的;它不能是变量。您也不能在模式(“非线性”模式)中多次使用相同的变量,也不能使用全局变量名称作为模式来尝试通过相等来匹配该事物;模式中的变量名称始终匹配任何内容,并通过该名称将其绑定到新的本地变量。
此外,函数是完全不透明的,无法进行比较。即使可以,这也不是正确的选择:Constructor token
表示类型为String -> token
的 any 函数,不一定是{{1}的构造函数之一}类型。
如果要动态执行此检查,则可以为令牌创建单独的标记类型,并与之进行比较:
Token
如果看来您的所有构造函数中的 all 只接受一个data Token = A String | B String
deriving (Eq,Read,Show)
data Constructor = ConstructorA | ConstructorB
deriving (Eq,Show)
tokenConstructor :: Token -> Constructor
tokenConstructor A{} = ConstructorA
tokenConstructor B{} = ConstructorB
tokenUsesConstructor :: Constructor -> Token -> Bool
tokenUsesConstructor c t = tokenConstructor t == c
参数,那么您可以使用一个小类型的代数(t + t = 2×t ):
String
或者,您可以让此函数接受谓词作为参数,然后测试很简单(并且甚至可能不需要单独的函数):
data Token = Token
{ tokenConstructor :: Constructor,tokenString :: String
}
deriving (Eq,Show)
tokenUsesConstructor c t = tokenConstructor t == c
isA :: Token -> Bool
isA A{} = True
isA _ = False
isB :: Token -> Bool
isB B{} = True
isB _ = False
type Predicate a = a -> Bool
matches :: Predicate token -> token -> Bool
matches p t = p t -- matches = ($) = id
还有更多涉及的解决方案,例如可以静态地知道此“标签”的GADT或使事物通用的各种方式,但是我认为它们是否合适取决于您尚未使用的实际用例的细节。 t描述。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。