[英]Types of Rules Don't Agree
我正在尝试用 SML 编写一个程序来解决以下问题:
使用卡片列表和目标进行游戏。 玩家有一个持有牌的列表,最初是空的。 玩家通过抽牌来移动,这意味着从卡片列表中移除卡片列表中的第一张卡片并将其添加到持有的卡片中,或者通过丢弃,这意味着选择一张持有的卡片来移除。 当玩家选择不再移动或持有的卡片值的总和大于目标时,游戏结束。 编写一个函数 officiate,“运行游戏”。 它需要一个卡片列表(卡片列表)、一个移动列表(玩家在每个点“做什么”)和一个 int(目标),并在处理完游戏结束时返回得分(部分或全部) 移动列表中的移动顺序。 使用本地定义的递归辅助函数,该函数接受多个参数,这些参数共同表示游戏的当前状态。 如上所述:
- 游戏以持有的牌为空列表开始。
- 如果没有更多动作,则游戏结束。 (玩家选择停止,因为移动列表为空。)
- 如果玩家丢弃了一些牌 c,则游戏继续(即,进行递归调用),持有的牌没有 c,牌列表不变。 如果 c 不在持有的牌中,则引发 IllegalMove 异常。
- 如果玩家抽牌并且卡片列表(已经)为空,则游戏结束。 否则,如果抽牌导致所持牌的总和超过目标,则游戏结束(抽牌后)。 其他游戏继续使用更大的手牌和更小的牌表。
这是我的解决方案:
datatype suit = Clubs | Diamonds | Hearts | Spades
datatype rank = Jack | Queen | King | Ace | Num of int
type card = suit * rank
datatype move = Discard of card | Draw
exception IllegalMove
fun remove_card (cs, c, e) =
let
fun delete_it (cs, c, e, count, acs) =
case cs of
[] => if count = 0 then raise e else acs
| cp::cs' => if cp = c andalso count = 0
then delete_it (cs', c, e, count + 1, acs)
else
if cp = c then delete_it (cs', c, e, count + 1, [cp] @ acs) else delete_it (cs', c, e, count, [cp] @ acs)
in
delete_it (cs, c, e, 0, [])
end
fun sum_cards (loc) =
let
fun sum_it (loc, sum) =
case loc of
[] => sum
| c::loc' => sum_it (loc', sum + card_value (c))
in
sum_it (loc, 0)
end
fun score (loc, goal) =
let
val sum = sum_cards (loc)
val all_same = all_same_color (loc)
in
let
fun prem_score (sum, goal) =
if sum > goal
then 3 * (sum - goal)
else goal - sum
in
let
val pre_score = prem_score (sum, goal)
fun final_score (all, pre) =
if all
then pre div 2
else pre
in
final_score (all_same, pre_score)
end
end
end
fun officiate (loc, lom, goal) =
let
fun get_score (lcards, lohc, lmoves, goal, e) =
case lmoves of
[] => score (lcards, goal)
| Draw::lmoves' => case lcards of
[] => score (lcards, goal)
| c::loc' => if sum_cards (c) > goal
then score (lcards, goal)
else get_score (loc', c::lohc, lmoves', goal, e)
| d::lmoves' => case d of
Discard c => get_score (loc, remove_card (lohc, c, e), lmoves', goal, e)
in
get_score (loc, [], lom, goal, IllegalMove)
end
函数sum_cards
返回给定卡片列表的值总和。 score
函数返回游戏的分数,而remove_card
返回一个卡片列表减去提供的卡片。 所有这些功能都运行良好,但问题出在officiate
功能上,因为我尝试使用另外两个辅助功能但没有运气。 这是错误日志:
hw2.sml:196.17-196.60 Error: operator and operand don't agree [tycon mismatch]
operator domain: (suit * rank) list * (suit * rank) list list * 'Z * int *
'Y
operand: (suit * rank) list list * (suit * rank) list list *
move list * int * 'Y
in expression:
get_score (loc',c :: lohc,lmoves',goal,e)
hw2.sml:198.29-198.78 Error: operator and operand don't agree [tycon mismatch]
operator domain: (suit * rank) list list * (suit * rank) list * exn
operand: (suit * rank) list list * card * 'Z
in expression:
remove_card (lohc,c,e)
hw2.sml:192.27-198.78 Error: types of rules don't agree [tycon mismatch]
earlier rule(s): (suit * rank) list list -> int
this rule: move list -> 'Z
in rule:
:: (d,lmoves') =>
(case d
of Discard c => get_score (<exp>,<exp>,<exp>,<exp>,<exp>))
hw2.sml:192.27-198.78 Error: case object and rules don't agree [tycon mismatch]
rule domain: (suit * rank) list list
object: (suit * rank) list
in expression:
(case lcards
of nil => score (lcards,goal)
| :: (c,loc') =>
if sum_cards <exp> > goal
then score (<exp>,<exp>)
else get_score (<exp>,<exp>,<exp>,<exp>,<exp>)
| :: (d,lmoves') =>
(case d
of Discard <pat> => get_score <exp>))
val it = () : unit
我认为这是因为我使用了多个 case 表达式。 任何帮助将不胜感激!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.