所以我正在研究一个函数,从int列表中找到一些有效的算术运算到目标数。它不允许使用throw / callac。只有add和mul是有效的算术运算,它们是左关联的。
datatype operation = ADD | MULT
(* find_op: int -> int list -> (operatino list -> 'a) -> (unit -> 'a) -> 'a *)
fun find_op x [] s k = k()
| find_op x [y] s k = if x=y then s([]) else k()
| find_op x (y1::y2::ys) s k =
let
val add = find_op x ((y1+y2)::ys) (fn a => s(ADD::a)) k
val mul = find_op x ((y1*y2)::ys) (fn a => s(MULT::a)) k
in
need some work here
end
该功能应如下所示:
给定列表[1,1,2,~1]和目标号码~4,被操作列表应为[ADD,ADD,MULT]或[ADD,MULT,MULT],因为(((1 + 1) )+2)* ~1)=((1 + 1) 2 ~1)= ~4。但是[MULT,ADD,MULT]无效,因为(((1 * 1)+2)* ~1)= ~3。
我很困惑如何检查返回的结果是否为k()。使用=来检查返回值是不可能的,因为它是多态的。有没有办法解决这个问题?
答案 0 :(得分:1)
您需要做的是使用这两种策略,首先尝试通过ADD
减少数字,然后通过MULT
减少数字,但依次。为此,您需要为第一个选择的策略的结果提供自定义故障延续(k
)。如果该策略失败,则在继续失败中尝试第二种策略。
你不能同时尝试这两种策略并让它们都成功。函数类型不允许返回多个正确答案。为此,您需要成功延续的类型为operation list list
。
datatype operation = ADD | MULT
fun opToString ADD = "ADD"
| opToString MULT = "MULT"
(* find_op: int -> int list -> (operation list -> 'a) -> (unit -> 'a) -> 'a *)
fun find_op x [] s k = k ()
| find_op x [y] s k = if x = y then s [] else k ()
| find_op x (y1 :: y2 :: ys) s k =
let
(* You need a custom failure continuation that tries the MULT variant
* if the ADD one fails.
*)
fun whenAddFails () =
find_op x ((y1 * y2) :: ys) (fn a => s (MULT :: a)) k
val add =
find_op x ((y1 + y2) :: ys) (fn a => s (ADD :: a)) whenAddFails
in
add
end
fun test () =
let
val opList = [1,1,2,~1]
val target = ~4
fun success ops =
"success: " ^ (String.concatWith " " (List.map opToString ops))
fun failure () =
"couldn't parse numbers as an operation list"
in
find_op target opList success failure
end