小编Lho*_*ooq的帖子

OCaml方差(+'a,-a)和不变性

写完这段代码之后

module type TS = sig
  type +'a t
end

module T : TS = struct
  type 'a t = {info : 'a list}
end
Run Code Online (Sandbox Code Playgroud)

我意识到我需要info变得可变.

我写道,然后:

module type TS = sig
  type +'a t
end

module T : TS = struct
  type 'a t = {mutable info : 'a list}
end
Run Code Online (Sandbox Code Playgroud)

但是,出乎意料,

Type declarations do not match:
  type 'a t = { mutable info : 'a list; }
is not included in
  type +'a t
Their variances …
Run Code Online (Sandbox Code Playgroud)

ocaml covariance contravariance invariance

18
推荐指数
2
解决办法
814
查看次数

如何在Reason ML中声明地图类型?

Reason ML优于JavaScript的一个优点是它提供了Map一种使用结构相等而不是引用相等的类型.

但是,我找不到这个用法的例子.

例如,我如何声明一个scores字符串映射到整数的类型?

/* Something like this */
type scores = Map<string, int>; 
Run Code Online (Sandbox Code Playgroud)

我将如何构建一个实例?

/* Something like this */
let myMap = scores();

let myMap2 = myMap.set('x', 100);
Run Code Online (Sandbox Code Playgroud)

ocaml dictionary reason reasonml

12
推荐指数
2
解决办法
2336
查看次数

使用 dune 将生成的可执行文件复制到我的根目录中

假设我有一个具有以下结构的简单项目:

\n
.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 dune-project\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 src\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 bin\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 dune\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 main.ml\n
Run Code Online (Sandbox Code Playgroud)\n

dune-project

\n
(lang dune 2.7)\n(name myproject)\n\n(package\n (name myproject)\n (synopsis "myproject")\n (description "Basic project")\n)\n
Run Code Online (Sandbox Code Playgroud)\n

dune

\n
(executable\n (name main)\n (public_name myproject)\n)\n
Run Code Online (Sandbox Code Playgroud)\n

编译时,我有一个具有以下结构的dune build新目录:_build

\n
_build\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 default\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 dune-project\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 META.myproject\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 myproject.dune-package\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 myproject.install\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 src\n\xe2\x94\x82\xc2\xa0\xc2\xa0     \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 bin\n\xe2\x94\x82\xc2\xa0\xc2\xa0         \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 dune\n\xe2\x94\x82\xc2\xa0\xc2\xa0         \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 main.exe\n\xe2\x94\x82\xc2\xa0\xc2\xa0         \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 main.ml\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 install\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 default\n\xe2\x94\x82\xc2\xa0\xc2\xa0     \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 bin\n\xe2\x94\x82\xc2\xa0\xc2\xa0     \xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 myproject -> ../../../default/src/bin/main.exe\n\xe2\x94\x82\xc2\xa0\xc2\xa0     \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 lib\n\xe2\x94\x82\xc2\xa0\xc2\xa0         \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 myproject\n\xe2\x94\x82\xc2\xa0\xc2\xa0             \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 dune-package -> ../../../../default/myproject.dune-package\n\xe2\x94\x82\xc2\xa0\xc2\xa0             \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 META -> …
Run Code Online (Sandbox Code Playgroud)

ocaml ocaml-dune

5
推荐指数
1
解决办法
751
查看次数

无法仅在mli文件中定义例外

好吧,这主要是关于好奇心,但我发现它太奇怪了.

我们假设我有这个代码

sig.mli

type t = A | B
Run Code Online (Sandbox Code Playgroud)

main.ml

 let f = 
   let open Sig in
   function A | B -> ()
Run Code Online (Sandbox Code Playgroud)

如果我编译,一切都会工作.

现在,让我们尝试修改 sig.mli

sig.mli

type t = A | B
exception Argh
Run Code Online (Sandbox Code Playgroud)

main.ml

main.ml

 let f = 
   let open Sig in
   function 
     | A -> ()
     | B -> raise Argh
Run Code Online (Sandbox Code Playgroud)

让我们尝试编译它:

> ocamlc -o main sig.mli main.ml
  File "main.ml", line 1:
  Error: Error while linking main.cmo:
  Reference to undefined global `Sig'
Run Code Online (Sandbox Code Playgroud)

好吧,是不是因为我添加了例外?也许这意味着异常就像函数或模块一样,需要适当的实现.

但是,如果我写的话怎么办?

main.ml

 let …
Run Code Online (Sandbox Code Playgroud)

ocaml module exception signature

3
推荐指数
1
解决办法
98
查看次数

使用 monad 简化重复模式

我实际上不确定这对 monad 是否可行,或者是否应该用它们来完成,并且我正在寻找解决方案,而不是用 monad 解决它(如果 monad 不是解决方案)。

假设我有以下代码(经过简化,但想法就在这里):

module IM = Map.Make (Int)

let f k v m =
  if IM.mem k m then (m, true)
  else (IM.add k v m, false)

let a =
  let m = IM.empty in
  let m, res = f 0 "Zero" m in
  if res then
    let m, res = f 1 "One" m in
    if res then f 2 "Two" m else (m, res)
  else (m, res)
Run Code Online (Sandbox Code Playgroud)

我重复了好多次:

let value, boolean = function …
Run Code Online (Sandbox Code Playgroud)

monads ocaml

3
推荐指数
1
解决办法
90
查看次数

带有可选参数的Printf错误

假设我写了这个函数:

let f ?(x=0) fmt y = Format.fprintf fmt "%d" (x+y)
Run Code Online (Sandbox Code Playgroud)

它的类型是: ?x:int -> Format.formatter -> int -> unit

我可以指定x或不指定.

现在,让我们这样称呼它:

let () = Format.printf "%a@." f 0
Run Code Online (Sandbox Code Playgroud)

我有这个错误:

Error: This expression has type ?x:int -> Format.formatter -> int -> unit
       but an expression was expected of type Format.formatter -> 'a -> unit
Run Code Online (Sandbox Code Playgroud)

好吧,我不明白为什么这会是一个问题.参数是可选的,如果我不说它应该没问题,不是吗?(写作 Format.printf "%a" (f ~x:0) 0 很明显,但有可选参数的意义何在?)

我的意思是,如果我声明我的函数是这样的:

let f ?(x=0) () fmt y = Format.fprintf fmt "%d" (x+y)
Run Code Online (Sandbox Code Playgroud)

它的类型是:?x:int -> () -> …

ocaml

2
推荐指数
1
解决办法
128
查看次数

迭代器,枚举和序列之间的区别

我想了解ocaml中迭代器,枚举和序列之间的区别

enumeration:
type 'a t = {
  mutable count : unit -> int; (** Return the number of remaining elements       in the enumeration. *)
  mutable next  : unit -> 'a;  (** Return the next element of the   enumeration or raise [No_more_elements].*)
  mutable clone : unit -> 'a t;(** Return a copy of the enumeration. *)
  mutable fast  : bool;        (** [true] if [count] can be done without reading all elements, [false] otherwise.*)
}
sequence:

type 'a node =
| Nil …
Run Code Online (Sandbox Code Playgroud)

ocaml

2
推荐指数
1
解决办法
334
查看次数

在运行时加载资源文件

假设我有这样的架构:

\n\n
.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 Cargo.lock\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 Cargo.toml\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 src/\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 main.rs\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 rsc/\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file.xml\n
Run Code Online (Sandbox Code Playgroud)\n\n

我想在每次运行时加载file.xml以填充一些表。为此我可以写:

\n\n
.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 Cargo.lock\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 Cargo.toml\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 src/\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 main.rs\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 rsc/\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file.xml\n
Run Code Online (Sandbox Code Playgroud)\n\n

但如果我不从 运行程序,相对路径将不起作用src

\n\n

我可以执行以下操作:

\n\n
use std::fs::File;\nuse std::path::Path;\n\nfn open<P: AsRef<Path>>(path: P) {\n    let _ = File::open(path).unwrap();\n    println!("file opened");\n}\n\nfn main() {\n    open("../rsc/file.xml");\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

但这将在编译时完成,这意味着更改file.xml意味着重新编译程序,因此在可维护性方面完全不安全。

\n\n

我可以看到的另一个选项是将rsc路径作为我的程序的参数,但我发现它有点麻烦,因为这不是一个可选参数,我真的需要知道我的rsc目录在哪里,并且我知道我的板条箱将具有这种架构。

\n\n

有什么我看不到的吗?

\n\n

我看到这篇文章:如何避免 Rust 中的硬编码值

\n\n

但我的问题总结在这一部分:

\n\n
\n

如果您正在部署二进制文件,则可能必须提供应用程序应找到其资源的路径。

\n
\n\n

而且没有其他的精确性。

\n

file rust

2
推荐指数
1
解决办法
2009
查看次数

类型级皮亚诺算术:类型构造函数将逃逸其范围

我尝试在 Ocaml 中的类型级别上实现 Peano 算术,但遇到了一个问题:

module Nat = struct
  type zero = Z

  type 'a succ = S

  type 'a nat = Zero : zero nat | Succ : 'a nat -> 'a succ nat
end
Run Code Online (Sandbox Code Playgroud)

现在,如果我想实现add,关于此操作的两个公理是:

福尔 X.  x + 0 = x

对于所有 x y。 x + succ y = succ (x + y)

我试过

let rec add : type n1 n2. n1 nat -> n2 nat -> 'a nat =
  fun a b -> match b with Zero -> a | Succ b' -> Succ (add a b')
Run Code Online (Sandbox Code Playgroud)

9 |    fun a b …
Run Code Online (Sandbox Code Playgroud)

ocaml

2
推荐指数
1
解决办法
255
查看次数

在函数签名中包含模块签名和该模块类型的值

我只想有一个在 Hashtbls 上通用的简单函数,所以我写了这个:

let iter_htbl (type a) (module H : Hashtbl.S with type key = a) htbl =
  H.iter (fun _key _v -> ()) htbl
Run Code Online (Sandbox Code Playgroud)

这给了我以下错误:

53 |   H.iter (fun _key _v -> ()) htbl
                                  ^^^^
Error: This expression has type 'a but an expression was expected of type
         'b H.t
       The type constructor H.t would escape its scope
Run Code Online (Sandbox Code Playgroud)

如果我写:

53 |   H.iter (fun _key _v -> ()) htbl
                                  ^^^^
Error: This expression has type 'a but an expression was …
Run Code Online (Sandbox Code Playgroud)

polymorphism ocaml first-class-modules

2
推荐指数
1
解决办法
71
查看次数

代数数据类型的模式匹配

这是一个悬而未决的问题,但我从未设法找到令我高兴的解决方案.

假设我有这种代数数据类型:

type t = A of int | B of float | C of string
Run Code Online (Sandbox Code Playgroud)

现在,假设我想写一个compare函数 - 因为我想把我的值放在一个Map例子中 - 我会像这样写:

let compare t1 t2 =
  match t1, t2 with
    | A x, A y -> compare x y
    | A _, _ -> -1
    | _, A _ -> 1
    | B x, B y -> compare x y
    | B _, _ -> -1
    | _, B _ -> 1
    | C x, C …
Run Code Online (Sandbox Code Playgroud)

ocaml pattern-matching algebraic-data-types

1
推荐指数
1
解决办法
382
查看次数

递归函数中的大整数的异常Stack_overflow

我的Quicksort代码适用于N的某些值(列表大小),但对于较大的值(例如,N = 82031),OCaml返回的错误是:

致命错误:异常Stack_overflow.

我究竟做错了什么?
我是否应该创建一个迭代版本,因为OCaml不支持大值的递归函数?

let rec append l1 l2 =
  match l1 with
    | [] -> l2
    | x::xs -> x::(append xs l2)


let rec partition p l =
  match l with
    | [] -> ([],[])
    | x::xs ->
      let (cs,bs) = partition p xs in
      if p < x then
        (cs,x::bs)
      else
        (x::cs,bs)


let rec quicksort l = 
  match l with
  | [] -> []
  | x::xs ->
      let (ys, zs) = partition x xs in
      append …
Run Code Online (Sandbox Code Playgroud)

stack-overflow ocaml fatal-error

1
推荐指数
1
解决办法
257
查看次数

使用相互递归

我想执行此代码,但我有这个错误.OCaml中是否存在相互递归?

错误:未绑定值quicksort您的意思是tquicksort?

我的问题:

let rec tquicksort lm l lM = 
    match l with
        | [] -> unirL(unir (rev lm) lM)
        | lx::lxs -> let (la, lb) = part lx lxs in
                    if nroelem la < nroelem lb then 
                        tquicksort (quicksort (la::lm)) lb lM
                    else 
                        tquicksort lm la (quicksort (lb::lM));;
let quicksort l = tquicksort [] l [];;
Run Code Online (Sandbox Code Playgroud)

recursion ocaml

0
推荐指数
1
解决办法
448
查看次数