我正在通过尝试编写一些我认为有趣的东西来艰难地学习Haskell,目前我正在尝试弄清楚如何为特定的解析问题在Haskell中推导出Semiring。
class Semiring s where
zero, one :: s
mul, add :: s -> s -> s
instance Semiring Bool where
zero = False
one = True
add = (||)
mul = (&&)
instance Semiring (Set String) where
zero = empty
one = singleton ""
add a b = union a b
mul a b = Data.Set.map (\(c, d) -> c ++ d) $ cartesianProduct a b
布尔型 ({true, false}, ∨, ∧, false, true) 版本运行良好。整数版本也是如此。最后一个称为解析森林,其表示形式为 (E, ∪, ·, ∅, {<>}),其中 E 是一组字符串,{<>} 是空字符串的集合。
当我尝试编译时,我得到:
Rigge… 115 10 error • Illegal instance declaration for ‘Semiring (Set String)’
(All instance types must be of the form (T a1 ... an)
where a1 ... an are *distinct type variables*,
and each type variable appears at most once in the instance head.
对我来说这没有太多意义。 Set String
是一个独特的类型,对吧,而class Semiring
的所有操作都应该纯粹地用字符串集合来表达。
如果您需要上下文,该项目位于Rigged Regular Expressions。 Bool版本仅报告正则表达式是否匹配; Int版本报告正则表达式可以匹配的不同方式的数量(即"a"〜/(a|a*)/
将返回2
,因为有两个不同且唯一的子表达式匹配); ParseForest不应返回方式的数量,而应返回所有可能的方式集合-但是它不能,因为我不明白为什么不能使用具体的数据类型Set String
,而其他具体的数据类型如Int
或Bool
可以正常工作。
String
不是类型变量。你漏掉了错误信息的一个关键部分,它告诉你如果启用FlexibleInstances
扩展(可以在文件顶部加入{-# LANGUAGE FlexibleInstances #-}
),那么它就会起作用。 - David Young