为什么使用自定义活动模式对元组做模式匹配时无法通过编译?
F#活动模式编译错误原因及修复
错误原因
你遇到的编译报错是对F#活动模式的匹配规则理解偏差导致的,具体问题有两个:
- 你定义的
(|Left|) i = i = 0、(|Top|) j = j = 0这类属于完整活动模式,作用是把输入值转换为另一个值(这里是转换为bool类型的判断结果),匹配时必须为转换后的返回值指定匹配规则。你直接写| Left没有给返回的bool值指定匹配目标,编译器默认你要匹配unit类型的(),自然触发「应具有类型bool,却得到unit」的类型错误。 - 你定义的
(|Right|) w i = i = w - 1、(|Bottom|) h j = j = h - 1属于带参数的完整活动模式,第一个参数是匹配时传入的配置值,处理输入后同样返回bool值,你原来的写法Right w、Bottom h没有处理返回的bool结果,无法实现「满足条件就匹配」的预期逻辑。
修复方案
有两种常用的修复方式都可以实现你的预期效果:
方案1:修改匹配语法,显式匹配返回的true值
不需要修改活动模式定义,仅补充bool值的匹配条件即可:
let (|Left|) i = i = 0 let (|Top|) j = j = 0 let (|Right|) w i = i = w - 1 let (|Bottom|) h j = j = h - 1 let test w h (i, j) = match i, j with | (Left true , Top true ) -> 1 | (Left true , Bottom h true ) -> 2 | (Right w true, Top true ) -> 3 | (Right w true, Bottom h true ) -> 4 | (_ , _ ) -> 5
测试结果:
test 100 100 (0,0)返回1,符合预期test 100 100 (99,99)返回4,符合预期
方案2:改用部分活动模式(更推荐)
如果仅需要做条件匹配、不需要捕获活动模式的返回值,更符合F#习惯的写法是使用部分活动模式,语法和你最初的预期完全一致:
// 部分活动模式用|_|标识,满足条件返回Some(),否则返回None let (|Left|_|) i = if i = 0 then Some() else None let (|Top|_|) j = if j = 0 then Some() else None let (|Right|_|) w i = if i = w - 1 then Some() else None let (|Bottom|_|) h j = if j = h - 1 then Some() else None let test w h (i, j) = match i, j with | (Left , Top ) -> 1 | (Left , Bottom h) -> 2 | (Right w, Top ) -> 3 | (Right w, Bottom h) -> 4 | (_ , _ ) -> 5
内容的提问来源于stack exchange,提问作者redcurry
相关产品推荐
相关产品推荐

