Haskell函数运行报错求助:无法输出符合条件的Predicate列表
问题分析与解决
你的代码核心问题在于:Predicate Thing本质是Thing -> Bool类型的函数,而Haskell默认不为函数提供Show实例——你没法直接打印一个函数,这就是GHCi报错No instance for Show (Thing -> Bool)的原因。你想要输出[isBig, isDisc, isOrange, isThick]这种函数名字符串,但运行时函数和它的代码标识符没有绑定关系,必须手动关联才能实现。
解决方案1:用元组绑定属性名与函数
直接用字符串存储属性名,和对应的判断函数组成元组,调整代码如下:
type Predicate a = a -> Bool -- 存储(属性名字符串,判断函数)的列表 properties :: [(String, Predicate Thing)] properties = [("isBlue", isBlue), ("isThick", isThick), ("isThin", isThin), ("isOrange", isOrange), ("isDisc", isDisc), ("isSquare", isSquare), ("isBig", isBig), ("isSmall", isSmall)] -- 返回匹配的属性名字符串列表 propertiesOf :: Thing -> [String] propertiesOf x = [name | (name, prop) <- properties, prop x]
调用propertiesOf会返回你预期的字符串列表,比如["isBig", "isDisc", "isOrange", "isThick"],可以直接在GHCi中打印。
解决方案2:自定义带Show实例的Property类型
如果希望输出格式更贴近你想要的[isBig, isDisc...](不带引号),可以自定义数据类型并实现Show实例:
type Predicate a = a -> Bool data Property = Property String (Predicate Thing) -- 让Property实例Show时只输出名字 instance Show Property where show (Property name _) = name properties :: [Property] properties = [Property "isBlue" isBlue, Property "isThick" isThick, Property "isThin" isThin, Property "isOrange" isOrange, Property "isDisc" isDisc, Property "isSquare" isSquare, Property "isBig" isBig, Property "isSmall" isSmall] propertiesOf :: Thing -> [Property] propertiesOf x = [prop | prop@(Property _ p) <- properties, p x]
此时调用propertiesOf myThing并打印,结果就是[isBig, isDisc, isOrange, isThick],完全符合你的预期。
补充说明
Haskell中函数是一等公民,但函数本身没有“可显示”的默认行为——因为函数的逻辑无法被自动转换成可读的字符串。你必须显式将函数和它的名字关联,才能在运行时输出对应的标识。
内容的提问来源于stack exchange,提问作者user27519555
相关产品推荐
相关产品推荐

