我正在使用 opam 開關:5.0.0~beta1
我在玩一些簡單的功能(在 utop 上):
type _ Effect.t = Foo : (unit -> unit) -> unit Effect.t
let a = try perform (Foo (fun () -> Printf.printf "Hello from Foo\n ")) with
| Unhandled (Foo f) -> f ();;
Output: Hello from Foo
val a: unit = ()
這很好用。但是當我們改變Foo效果的定義時,
type _ Effect.t = Foo : ('a -> unit) -> unit Effect.t
let a = try perform (Foo (fun n -> Printf.printf "Hello from Foo\n ")) with
| Unhandled (Foo f) -> f 45;;
Error: This expression has type int but an expression was expected of type
$Foo_'a
在這里我知道它需要'a作為輸入,但是在呼叫函式時,它不應該將型別推斷為int并替換'a為int并相應地執行函式嗎?我想用不同的引數呼叫f函式Foo effect。
這是另一個例子:
type _ Effect.t = Suspend : 'a -> unit Effect.t
let a = try perform (Suspend 32) with
| Unhandled (Suspend x) -> x;;
Error: This expression has type $Suspend_'a
but an expression was expected of type $Unhandled_'a
在這里,我知道 ( ) 的回傳值,try _ with即 ( unit) 應該是$Unhandled_ 'a. 但我也想知道,什么是$Unhandled_ 'a型別?正常與 有何'a不同$Unhandled_ 'a?怎么回到$Unhandled_ 'a這里?為什么有這個特殊用途$Unhandled?它的范圍是什么(在我使用以下代碼的一些示例中,
type _ Effect.t = Foo : ('a -> unit) -> unit Effect.t
let p = try Lwt.return (some_function x) with
| Unhandled (Foo f) -> let (pr, res) = Lwt.task () in
let wkup v = (Lwt.wakeup res v; ()) in
f wkup;
pr
我也收到錯誤:
This expression has type $Unhandled_'a Lwt.t
but an expression was expected of type 'a Lwt.t
The type constructor $Unhandled_'a would escape its scope
)?
為什么有
The type constructor $Unhandled_'a would escape its scope
錯誤?
uj5u.com熱心網友回復:
效果部分在這里是一個紅鯡魚,根本問題源于 GADT 中存在量化型別的概念。
當您有定義為的 GADT 時
type t = Foo : ('a -> unit) -> t
的型別Foo意味著您可以t為任何型別'a和任何型別的函式構造 a 'a -> unit。例如:
let l = [Foo ignore; Foo print_int]
然而,一旦你構造了這樣的值,你就不再知道使用了哪種型別來構造該值。如果你有一個價值
let test (Foo f) = ...
您只知道存在某種具有 type 的'a型別。這就是為什么該型別被稱為存在型別(也就是我們只知道它存在的型別)。要記住的重要事情是您不知道哪個. 因此,您無法應用該功能,因為應用錯誤將是型別錯誤。f'a -> unit'a'a'a
換句話說,裝箱的函式Foo f永遠不能在任何值上呼叫。這是比任何型別稍微微妙的變體
type any = Any: 'a -> any
其中建構式Any獲取任何型別的值并將其放入永遠無法從中提取的黑匣子中。
在某種程度上,GADT 中存在量化的型別變數生活在他們自己的世界中,他們無法逃脫它。但如果這個內心世界足夠大,它們仍然很有用。例如,我可以將一個值與一個列印該值的函式捆綁在一起,然后使用以下命令忘記該值的型別:
type showable = Showable: {x:'a; print:'a -> unit} -> showable
在這里,我可以呼叫該print值的函式,x因為我知道無論是什么,'a它都是相同'a的x和print:
let show (Showable {x;print}) = print x
因此我可以在串列中存盤一些可顯示的值
let l = [ Showable(0, print_int), Showable("zero", print_string)]
稍后列印
let () = List.iter show l
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/525219.html
上一篇:Postgresql例外記錄
