我在OCaml中编码了一种van Laarhoven镜头,但由于价值限制我很难.
相关代码如下
module Optic : sig
type (-'s, +'t, +'a, -'b) t
val lens : ('s -> 'a) -> ('s -> 'b -> 't) -> ('s, 't, 'a, 'b) t
val _1 : ('a * 'x, 'b * 'x, 'a, 'b) t
end = struct
type (-'s, +'t, +'a, -'b) t =
{ op : 'r . ('a -> ('b -> 'r) -> 'r) -> ('s -> ('t -> 'r) -> 'r) }
let lens …Run Code Online (Sandbox Code Playgroud) 我不明白F#中的价值限制是如何运作的.我已经阅读了wiki中的解释以及MSDN文档.我不明白的是:
例如,为什么这给了我一个价值限制错误(取自这个问题):
let toleq (e:float<_>) a b = (abs ( a - b ) ) < e
Run Code Online (Sandbox Code Playgroud)
但这不是:
let toleq e (a:float<_>) b = (abs ( a - b ) ) < e
Run Code Online (Sandbox Code Playgroud)这一点可以概括......
let is_bigger a b = a < b
Run Code Online (Sandbox Code Playgroud)
但这不是(它被指定为int):
let add a b = a + b
Run Code Online (Sandbox Code Playgroud)为什么带隐式参数的函数会生成值限制:
这个:
let item_count = List.fold (fun acc _ -> 1 + acc) 0
Run Code Online (Sandbox Code Playgroud)
对此:
let item_count l = List.fold (fun acc _ …Run Code Online (Sandbox Code Playgroud)是否可以部分应用诸如bprintf并根据其初始使用限制其功能?
我想做以下事情:
let builder = new System.Text.StringBuilder()
let append = Printf.bprintf builder
append "%i" 10
append "%s" string_value
Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一个函数,它接受一个整数和一个三元组并返回给定位置的三元组元素(练习5.3来自Hickey的书).Triplet应该能够包含不同类型的元素.
我想,如果我写了3个小函数,每个函数返回三元组的特定元素并使我的大函数相应地返回其中一个,那么它就可以做到,但它不起作用.
我试图摆弄这种"eta-expansion"概念,但我没有得到它.
let nth1 (a, _, _) = a
let nth2 (_, b, _) = b
let nth3 (_, _, c) = c
let nth i = match i with
| 1 -> nth1
| 2 -> nth2
| _ -> nth3
let main = printf "%d\n" (nth 1 ("hello", 2, 'c'))
Run Code Online (Sandbox Code Playgroud)
所以它应该只写"2".有什么建议?
我对OCaml中的弱多态性有点困惑.
请参阅以下代码片段,我在其中定义一个函数remember:
let remember x =
let cache = ref None in
match !cache with
| Some y -> y
| None -> cache := Some x; x
;;
Run Code Online (Sandbox Code Playgroud)
编译器可以推断出多态类型'a -> 'a,并cache在本地使用.
但是当我修改上面的代码时
let remember =
let cache = ref None in
(fun x -> match !cache with
| Some y -> y
| None -> cache := Some x; x)
;;
Run Code Online (Sandbox Code Playgroud)
编译器推断出弱多态类型'_a -> '_a,似乎cache在调用之间共享remember.
为什么编译器在这里推断出弱多态类型以及为什么要 …
我已经阅读了F#中关于价值限制的所有内容,但我仍然不理解它.我有以下代码:
type tree<'a> =
| Nil
| Node of (tree<'a> * 'a * tree<'a>)
let rec flatten = function
| Nil -> []
| Node ( Nil, b, Nil ) -> [b]
| Node ( l, h, p ) -> List.concat [(flatten l);[h];(flatten p)]
Run Code Online (Sandbox Code Playgroud)
并且编译器显示错误:
error FS0030: Value restriction. The value 'it' has been inferred to have generic type
val it : '_a list
Either define 'it' as a simple data term, make it a function with explicit arguments or, …Run Code Online (Sandbox Code Playgroud) 我有一个F#功能:
let removeEven (listToGoUnder : _ list) =
let rec listRec list x =
match list with
| [] -> []
| head::tail when (x%2 = 0) -> head :: listRec (tail) (x+1)
| head::tail -> listRec (tail) (x+1)
listRec listToGoUnder 0
Run Code Online (Sandbox Code Playgroud)
它会删除列表中偶数索引处的所有元素.它是有效的,如果我给列表一些输入,就像removeEven ['1';'2';'3']我得到['1';'3']我应该的.但是当我插入一个空列表作为参数时,我收到此错误:
stdin(78,1):错误FS0030:值限制.值'it'被推断为具有泛型类型
val it:'_ a list将'it'定义为一个简单的数据项,使其成为具有显式参数的函数,或者,如果您不打算将其作为泛型,则添加类型注释.
帮忙,有人吗?
根据标准ML的定义(修订):
这个想法是对非扩展表达式的动态评估既不会生成异常也不会扩展内存的域,而对扩展表达式的评估可能会.
[§4.7,p19; 强调我的]
我在网上找到了很多关于ref-cell部分的信息,但几乎没有关于异常部分的信息.(一些消息来源指出,仍然可能会出现多态绑定Bind,并且这种不一致可能会产生类型理论和/或实现后果,但我不确定这是否相关.)
我已经能够想出一个与异常相关的不健全的东西,如果我没有弄错的话,只能通过价值限制来阻止; 但这种不健全并不取决于提出异常:
local
val (wrapAnyValueInExn, unwrapExnToAnyType) =
let exception EXN of 'a
in (EXN, fn EXN value => value)
end
in
val castAnyValueToAnyType = fn value => unwrapExnToAnyType (wrapAnyValueInExn value)
end
Run Code Online (Sandbox Code Playgroud)
那么,任何人都可以告诉我定义的内容,以及它为什么提到例外?
("生成异常"是否可能意味着生成异常名称,而不是生成异常数据包?)
我正在构建一个合并排序函数,我的split方法给了我一个值限制错误.我正在使用2个累积参数,这两个列表是由拆分产生的,我最后打包成一个元组用于返回.但是我得到了一个值限制错误,我无法弄清楚问题是什么.有没有人有任何想法?
let split lst =
let a = []
let b = []
let ctr = 0
let rec helper (lst,l1,l2,ctr) =
match lst with
| [] -> []
| x::xs -> if ctr%2 = 0 then helper(xs, x::l1, l2, ctr+1)
else
helper(xs, l1, x::l2, ctr+1)
helper (lst, a, b, ctr)
(a,b)
Run Code Online (Sandbox Code Playgroud)
任何输入都表示赞赏.
编辑:对不起大家,我以为我的小例子已经完成,结果不是。 我做了一个新的,真的应该是!
一旦我使用格式化程序作为 Scanf 或 Printf 函数的参数,格式化程序类型就会分别绑定到输入或输出通道。有没有办法让函数采用格式化程序(或字符串)并将其用作打印和读取的格式化程序?
let fmt = format_of_string "%d,%d";;
Scanf.sscanf "2,2" fmt (fun x y -> x,y);;
fmt;;
Run Code Online (Sandbox Code Playgroud)
给
- : (int -> int -> int * int, Scanf.Scanning.scanbuf, '_a, (int -> int -> int * int) -> int * int, (int -> int -> int * int) -> int * int, int * int) format6 = <abstr>
Run Code Online (Sandbox Code Playgroud)
这意味着后续Printf.printf fmt 1 2;;会给出类型错误。这适用于我尝试过的每种功能format_of_string和Scanf.format_from_string类似功能的组合。
例子:
module Thing = struct
(* Just …Run Code Online (Sandbox Code Playgroud)