You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell Pattern Synonyms等特性使用两类报错原因与解决方法咨询

模式同义词报错原因、解决方法与工作原理说明

第一个报错:non-bidirectional pattern synonym used in an expression

触发原因

你定义的IsTrue是单向模式同义词,仅声明了匹配规则(用<-表示),没有定义对应的构造逻辑,因此只能出现在模式匹配的位置,不能作为值/构造函数放在表达式中调用。你写的test10 = IsTrue "True"属于将单向模式同义词当作表达式使用,不符合语法规则。

解决方法

两种可选方案:

  1. 仅测试匹配功能:将test10改为模式匹配写法
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE GADTs #-}
pattern IsTrue :: Show a => a
pattern IsTrue <- ((== "True") . show -> True)
test10 = case "True" of
  IsTrue -> "匹配成功"
  _ -> "匹配失败"
  1. 改为双向模式同义词:补充构造逻辑,允许作为表达式使用
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE GADTs #-}
pattern IsTrue :: Show a => a
pattern IsTrue <- ((== "True") . show -> True)
  where IsTrue = read "True" -- 补充构造逻辑,返回show结果为"True"的值
test10 = IsTrue :: Bool -- 此时可作为表达式调用,取值为True

第二个报错:No instance for (Show T) arising from a use of ‘print’

触发原因

该报错和模式同义词本身无关:你定义的GADT类型T没有实现Show实例,在GHCi中直接运行test11时,GHC会默认调用print输出结果,而print要求参数实现Show类型类,因此触发报错。test11本身的编译逻辑是合法的。

解决方法

给T类型实现Show实例即可,可直接复用内部存储字段的Show能力:

{-# LANGUAGE GADTs #-}
{-# LANGUAGE PatternSynonyms #-}
data T where
  MkT :: (Show b) => b -> T
-- 手动实现Show实例
instance Show T where
  show (MkT x) = "MkT " ++ show x
pattern ExNumPat :: () => Show b => b -> T
pattern ExNumPat x = MkT x
test11 = ExNumPat True -- 运行会输出 "MkT True"

两类模式同义词的工作原理

1. 单向模式同义词

语法为pattern 模式名 <- 匹配逻辑,仅可用于模式匹配场景:

  • 匹配时会执行声明的匹配逻辑对目标值做校验/转换,符合条件则匹配成功。你定义的IsTrue结合了ViewPatterns扩展,匹配时会先对目标执行show,再判断结果是否等于"True",满足则匹配通过。
  • 没有声明构造逻辑,因此无法作为表达式/构造函数使用。

2. 双向模式同义词

包含两种写法:一种是pattern 模式名 参数 = 构造逻辑,另一种是单向模式后加where块补充构造逻辑,既可以用于模式匹配,也可以作为构造函数在表达式中使用:

  • 作为表达式使用时,等价于直接调用你声明的构造逻辑生成对应值,你定义的ExNumPat x = MkT x作为表达式调用时,等价于直接调用MkT构造T类型的值。
  • 作为模式匹配使用时,会匹配构造逻辑对应的取值,将内部字段绑定到参数上。
  • 模式同义词的双约束类型签名中,前一层()包裹的约束是匹配成功后对外提供的上下文,后一层约束是构造/使用该模式时需要满足的约束。

内容的提问来源于stack exchange,提问作者maxloo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 05:12:04