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

Haskell考试复习:非递归实现scoreHand函数求助

如何实现Haskell中scoreHand函数的非递归版本?

嘿,你的递归版本逻辑很清晰嘛!既然已经搞定了递归实现,那非递归版本其实可以借助Haskell的标准库函数或者列表推导式来轻松完成,完全不用自己写递归逻辑~

先回顾一下你已经完成的递归代码(方便对照):

import Data.Char
type PlayingCardValue = Char
scoreHand :: [PlayingCardValue] -> Int
scoreHand [] = 0
scoreHand (x:xs) = if x > '1' && x < '9' then digitToInt x + scoreHand (xs)
                   else if x == 'T' || x == 'J' || x == 'Q' || x == 'K' then 10 + scoreHand (xs)
                   else if x == 'A' then 11 + scoreHand (xs)
                   else 0 + scoreHand (xs)

方案1:用map+sum的函数组合实现

这个版本利用函数组合把“转换每个牌面到分值”和“求和”两个步骤结合起来,代码更简洁:

import Data.Char
type PlayingCardValue = Char

scoreHand :: [PlayingCardValue] -> Int
scoreHand = sum . map cardToValue
  where
    -- 定义单个牌面到分值的转换函数
    cardToValue :: PlayingCardValue -> Int
    cardToValue c
      | c `elem` ['2'..'9'] = digitToInt c  -- 2-9直接转对应数字
      | c `elem` ['T','J','Q','K'] = 10     -- 花牌都是10分
      | c == 'A' = 11                       -- A是11分
      | otherwise = 0                       -- 无效牌面得0分

逻辑解释:

  • map cardToValue会遍历输入的手牌列表,把每个PlayingCardValue转换成对应的分值,生成一个整数列表;
  • sum则把这个整数列表里的所有值加起来,得到总分;
  • 用.做函数组合,相当于scoreHand cards = sum (map cardToValue cards),只是写法更符合Haskell的函数式风格。

方案2:用列表推导式实现

如果你更习惯列表推导式的写法,也可以这样写,逻辑和上面完全一致:

import Data.Char
type PlayingCardValue = Char

scoreHand :: [PlayingCardValue] -> Int
scoreHand cards = sum [ getValue c | c <- cards ]
  where
    getValue c
      | c `elem` ['2'..'9'] = digitToInt c
      | c `elem` ['T','J','Q','K'] = 10
      | c == 'A' = 11
      | otherwise = 0

逻辑解释:

  • 列表推导式[ getValue c | c <- cards ]会逐个取出cards里的每个牌面c,计算它的分值,最终生成一个分值列表;
  • 再用sum对这个列表求和,就得到了手牌的总分。

这两个非递归版本都和你原来的递归版本逻辑完全对齐,包括对无效牌面返回0分的处理,放心用就好!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:47:39