F#编程问题解析与算法实现

25、声明序列:let mutable a = [] let f x = a <- (x :: a) f(1);; 会被 F# 接受。请解释原因。

这些声明不会被 F# 接受。声明 let mutable a = [] a 绑定到多态表达式 mutable [] 的值,该表达式不被视为值表达式,此声明会被多态表达式使用限制所拒绝。因为 F# 会在函数使用前推断 f 的类型为 'a -> unit ,后续调用 f 时可能会出现类型错误,如 f(1) f("ab") 类型检查虽能通过,但在计算 f("ab") 时会出现非法表达式 "ab"::[1]

26、使用 while 循环声明一个用于计算斐波那契数 Fn 的函数。提示:引入变量来存储先前计算的两个斐波那契数。

以下是使用 while 循环实现计算斐波那契数 $ F_n $ 的 F# 代码:

let fibonacci n =
    if n = 0 then 0
    elif n = 1 then 1
    else
        let mutable prev1 = 0
        let mutable prev2 = 1
        let mutable current = 0
        let mutable i = 2
        while i <= n do
            current <- prev1 + prev2
            prev1 <- prev2
            prev2 <- current
            i <- i + 1
        current

注:原答案中赋值语句使用了 = 是错误的,在 F# 里可变变量赋值要用 <-

27、考虑以下列表生成函数:let rec bigListK n k = if n=0 then k [] else bigListK (n-1) (fun res -> 1::k(res));; 调用 bigListK 130000 id 会导致栈溢出。分析这个问题。

该函数不是尾递归函数,每次递归调用都会在栈上创建一个新的栈帧。调用 bigListK 130000 id 时,会创建 130000 个连续的栈帧,超过了栈的最大容量,从而导致栈溢出。

对比来看,像 bigListA 这样的尾递归函数能避免栈溢出问题,它在内存不足时是因为堆耗尽。

28、考虑如下 bld.Delay 声明的“替代方案”: type MaybeClass() = ... member bld.Delay f:maybe<’a> = delay(start (f()));; 这个新声明无法达到预期效果。请解释原因。

预期效果是让 maybe{ce} 形式的表达式表示真正的配方,实际烹饪延迟到配方启动时。新声明中 delay(start (f())) 先对 f() 进行了 start 操作,这会提前执行 f() 中的计算,而不是延迟到 start 函数调用时,所以无法延迟计算,不能达到预期效果。

29、以下用于非空数字列表的文法使用了左递归:numberList ::= number | numberList number。一个严格遵循此文法结构的解析器如下:let rec numberLst = parser {let! n = number return [n] } <|> parser {let! ns = numberLst let! n = number return ns @ [n]};; 该解析器存在问题。分析该解析器并解释问题所在。

由于文法使用了左递归,对应的解析器会进入无限循环,无法正常工作。

30、解释使用左递归的表达式语法存在的问题。

该语法里 expr 能扩展为 expr addOp term term 也有类似情况,存在左递归。虽然理论上表达式推导步骤和构建表达式树步骤对应,但对应解析器会进入无限循环,所以不能用于此方法。

31、声明一个解析器组合器:pFold : (‘a -> ‘d -> ‘a) -> parser<’d> -> parser<’a> -> parser<’a>,使得如果 p 首先捕获值 a,之后重复使用 t 捕获值 d1, d2, …, dk,那么 pFold f t p 捕获值 a, a1 = f a d1, a2 = f a1 d2, …, ak = f ak−1 dk。使用这个解析器组合器以如下形式对 infixL 进行替代声明:let infixL op q p = pFold (fun … ) (pairOf op q) p ;;

以下是 pFold 解析器组合器的声明以及使用它对 infixL 进行替代声明的代码:

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值