2013-12-08 13 views
1

在StringCvt中解析函數可能會引發異常,如果他們發現任何錯誤,問題是引發的異常不包含任何精確的位置信息,因此它的調用者無法知道究竟在哪裏導致問題。我首先想到的一個直接的解決方案是提高包含問題流異常,例如,改變是否有可能在StringCvt.scanInt函數中引發精確的流位置信息異常?

if W32.<(largestPosInt32, word) 
then raise Overflow 
else SOME(fromWord32 word, rest) 

if W32.<(largestPosInt32, word) 
then raise (Overflow rest) 
else SOME(fromWord32 word, rest) 

異常Overflow將承擔額外rest。但rest屬於多態類型,換句話說,假設函數的類型爲(char, 'a) StringCvt.reader -> (int, 'a) StringCvt.reader,我想在此函數中引發異常exception ParseError of string * 'a,但我不知道如何在Standard ML中執行此操作。 請問有什麼其他解決方法?提前致謝。

再次更新。 我現在用一個仿函數來解決這個問題,但它不如一個簡單的函數那麼方便。骨架代碼,

functor Foo(structure arg : sig 
          type opaque 
          type stream 
          val refopaque : stream -> opaque 
          end) : 
sig 
type opaque 
type stream 
exception SomeError of string * opaque 
end = 
struct 
type opaque = arg.opaque 
type stream = arg.stream 
val refopaque = arg.refopaque 
exception SomeError of string * opaque 
fun parse getc cs 
... raise SomeError("error", refopaque cs) 
... 
end 
+0

問題是:你會如何處理這些信息?如果異常真的可以攜帶_any_類型(例如,存在量化),那麼在你發現異常的地方,你無法知道實際有效負載的類型,所以你不能用它來做任何事情。 –

+0

它不是_any_類型,而是一個由關閉函數綁定的類型變量,即在函數a *'b - >'b'中引發'b'異常類型的異常。寫完後,我想我知道這個問題。爲了讓其他人處理這個異常,應該在頂層聲明異常,並且不綁定任何類型變量,那麼就不可能使異常變爲多態。感謝您的評論,我想我明白了這個問題。 – MingyanGuo

回答

2

您可以在本地定義引用多態類型變量的異常,並且可以在本地引發並捕獲它們。例如:

fun 'a f(x : 'a) = 
    let 
     exception E of 'a 
     fun g() = raise E x 
     fun h() = g() handle E y => y 
    in 
     h() 
    end 

請注意,這不是一個多態的異常,雖然 - 它是相對於範圍類型'a單態,而你只能把它應用到該類型的值,即,只有x。因此,沒有辦法在全局範圍內定義這樣的異常,因爲全局範圍中不存在類型變量(它們應該在哪裏綁定或實例化?)。

在SML中不能有真正的多態異常。原則上,允許通過存在量化來實現這一點,但在實踐中它不會很有用。由於在匹配異常時無法知道類型,因此必須將該類型視爲完全抽象。例如:

exception E of 'a (* hypothetical existential exception *) 
fun f1() = raise E 1 
fun f2() = raise E "foo" 
fun g f = f() handle E x =>() (* type of x is abstract here *) 

的唯一用處不大的例子是像

exception E of ('a -> int) * 'a 
fun f1() = raise E(fn x => x, 1) 
fun f2() = raise E(String.size, "foo") 
fun g f = f() handle E(h, x) => h x 

但有什麼理由不與不需要存在類型的簡化版本替換此:

exception E of unit -> int 
fun f1() = raise E(fn() => 1) 
fun f2() = raise E(fn() => String.size "foo") 
fun g f = f() handle E h => h() 

在實踐中,沒有人可能想要在例外中傳遞一流的ADT ......

2

沒有任何障礙來聲明帶有抽象類型值的異常,所以我不知道我理解你的問題。該異常將在具有該類型的關聯值的抽象類型的簽名中聲明。

+0

對不起,我用了一個錯誤的名詞。總之,我想提出一個包含類型變量的異常。例如,在類型'a *'b - >'c的函數中引發包含'b的異常。問題已更新。非常感謝。 – MingyanGuo

相關問題