Haskell新手求教:如何实现中缀运算符<+合并两个手牌
解决Haskell自定义中缀运算符
<+>的绑定错误 嘿,刚看到你的问题,这是个Haskell初学者很容易踩的小坑,我来帮你理清楚!
首先,你遇到的错误The type signature for ‘<+’ lacks an accompanying binding,核心原因是运算符的定义语法不对。Haskell里不能用h1 (<+) h2 = undefined这种写法来定义中缀运算符——编译器会误解这个写法,找不到和类型签名对应的函数实现绑定,所以才报了错。
正确的运算符实现方式
我们需要用两种标准语法之一来定义<+>,同时还要把undefined替换成实际的手牌合并逻辑:
方式1:前缀式定义(把运算符括起来作为函数名)
data Rank = Numeric Integer | Jack | Queen | King | Ace data Suit = Hearts | Spades | Diamonds | Clubs data Card = Card Rank Suit data Hand = Empty | Add Card Hand -- 类型签名保持不变 (<+) :: Hand -> Hand -> Hand -- 用括号包裹运算符,以前缀函数的形式定义 (<+) Empty h2 = h2 -- 若第一个手牌为空,直接返回第二个手牌 (<+) (Add card h1Rest) h2 = Add card (h1Rest <+ h2) -- 递归将h1的每张卡依次放在h2前方
方式2:中缀式定义(直接用运算符写等式)
这种写法更贴合中缀运算符的直观使用习惯:
data Rank = Numeric Integer | Jack | Queen | King | Ace data Suit = Hearts | Spades | Diamonds | Clubs data Card = Card Rank Suit data Hand = Empty | Add Card Hand (<+) :: Hand -> Hand -> Hand Empty <+ h2 = h2 -- 空手牌与任何手牌合并,结果为对方 (Add card h1Rest) <+ h2 = Add card (h1Rest <+ h2) -- 递归遍历h1,把每张卡前置到合并结果中
实现逻辑说明
这个递归定义的核心思路是:
- 当第一个手牌
h1为空(Empty),直接返回第二个手牌h2; - 当
h1是Add card h1Rest(包含一张卡+剩余手牌),先保留当前的card,再递归合并h1Rest和h2,最后把card放在递归结果的最前面——这样就实现了把h1的所有卡置于h2上方的效果。
测试验证
你可以写个测试用例看看效果:
-- 创建两个测试手牌 testHand1 = Add (Card Ace Hearts) (Add (Card (Numeric 10) Spades) Empty) testHand2 = Add (Card King Diamonds) Empty -- 运行 testHand1 <+ testHand2 会得到: -- Add (Card Ace Hearts) (Add (Card (Numeric 10) Spades) (Add (Card King Diamonds) Empty))
这样就完美实现了你想要的手牌合并功能啦!
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

