[英]How to pass parameter to Shell.sh_one in Ocaml
當我將字節變量從Core_extended
傳遞給方法Shell.sh_one
, Core_extended
出現一個奇怪的錯誤:
Error: This expression has type bytes but an expression was expected of
type
('a, unit, bytes, bytes option) Core.Std.format4 =
('a, unit, bytes, bytes, bytes, bytes option) format6
有趣的是,如果我傳遞字節文字,沒有錯誤。 有人可以解釋Ocaml的這種行為嗎? 下面是Ocaml utop的列表:
# #require "core_extended";;
# open Core_extended.Std;;
# let cmd = "ls -al /";;
val cmd : bytes = "ls -al /"
# "ls -al /";;
- : bytes = "ls -al /"
# Shell.sh_one "ls -al /";;
- : bytes option =
Some
"lrwxrwxrwx 1 root root 30 sty 29 09:28 vmlinuz.old -> boot/vmlinuz-4.13.0-32-generic"
# Shell.sh_one cmd;;
Error: This expression has type bytes but an expression was expected of type
('a, unit, bytes, bytes option) Core.Std.format4 =
('a, unit, bytes, bytes, bytes, bytes option) format6
如果查看Core_extended.Shell.sh_one
的類型,您將看到以下內容
val sh_one: ('a,unit,bytes,string option) format4 -> 'a
這意味着sh_one
的第一個參數是格式字符串。 例如,可以將格式說明符與sh_one
一起sh_one
:
Shell.sh_one "ls -%s /" "al"
您的問題源於格式字符串類型,格式format4
和字符串或字節在OCaml中的類型不同。
然而,OCaml類型檢查器中有一點神奇之處在於它使字符串和格式字符串可以共享相同的文字語法:如果類型檢查器注意到預期的字符串文字類型實際上是格式字符串,它會重新解釋字符串文字作為格式字符串文字。
你可以通過比較自己在utop看看這個現象
let s = "A simple string";;
s:string =“一個簡單的字符串”
和
open CamlinternalFormatBasics
(* ^ this help with making the format readable *)
let fmt : _ format4 = "A format string"
val fmt:('a,'b,'c,'a)format4 =格式(String_literal(“一個簡單的字符串”,End_of_format),“一個簡單的字符串”)
顯式類型注釋的替代方法是使用format_of_string
函數,該函數將字符串文字標記為格式字符串文字
let fmt = format_of_string "A format string"
簡而言之,如果要在變量中存儲格式字符串,可以使用顯式類型注釋或format_of_string
雖然它們在語法上是相同的,但bytes
和format
類型是不同的。
這是由編譯器內部的一些黑魔法處理的,它基本上檢查它何時看到字符串,如果它綁定到格式類型。
在您的情況下,檢查是在創建cmd
。 在程序的這一點上,沒有辦法知道它將被用作格式字符串。 所以它給出了類型bytes
。 后來,你從明顯困惑的編譯器中得到了通常的“我不做轉換”。
let cmd : ('a,'b,'c,'d) Core.Std.format4 = "ls -al /";;
這里我只添加了一個類型信息,以便編譯器知道“這不是字符串,而是格式字符串”。 事情應該正常。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.