2017-10-20 140 views
0

我想編寫一個樣本函數,該函數接受任何類型的列表,並且僅當列表是一個實數列表時才返回頭元素。ML如何檢查列表類型並給出錯誤按摩?

否則,函數應該給出錯誤信息

。 。 。 E r r o r:操作符和操作數不是。 。 。

datatype typeR = Real of real 
fun head(xs) = 
    case xs of 
     [] => raise List.Empty | 
      Real (x::_) => x:real ; 

回答

1
(fn x:real list => hd x) [ 4 ,5 ]; 
out> error: Type error in function application 
(fn x:real list => hd x) [ 4.0 ,5.0 ]; 
out> it = 4.0: real 
+4

請添加您的代碼的說明。 –

+0

'(fn x:real list => hd x)'不包含任何類型的列表*,但僅包含實數列表。但是,只有當列表是一個reals *列表時,它纔會返回head元素,並且在不受reals列表影響時會產生類型錯誤。或者,'hd:real list - > real'。 –

2

這不是完全清楚你在做什麼之後 - 你不能寫一個函數,採用「任何類型」,然後檢查參數類型。
(編寫head(xs),沒有類型註釋,不會使head可以接收任意類型的函數,它的類型推斷。)

如果你想有一個功能typeR list -> real,您的主要錯誤是寫Real (x::_),你應該寫(Real x) :: _
即,

fun head(xs) = 
    case xs of 
     [] => raise List.Empty 
    | (Real x)::_ => x 

,或者更慣用,

fun head [] = raise List.Empty 
    | head (Real x :: _) = x 
0

首先一些反饋:

  • 此功能是容易失敗,因爲它僅接受其可能的餘量輸入。儘可能寫出全部功能。

  • raise Empty不會描述列表非空的情況,但第一個元素不包含實數。那麼應該提出另一個例外。

  • 以下需求是高度可疑的。

    否則,函數應該給錯誤消息

    。 。 。 E r r o r:操作符和操作數不是。 。 。

    它表明您不區分運行時異常和編譯時錯誤。這對於使用動態類型語言的編程經驗是有症狀的,其中錯誤和異常都是在程序啓動後處理的。

然後一些想法:

解釋在標準ML是同質的,這意味着它們可以僅是一種類型的在編譯的類型檢查階段確定的時間。有幾種方法可以解決這個問題並實現更多的動態輸入;

  • Using algebraic data types [wiki.haskell。組織]:

    datatype dynamic = R of real 
           | I of int 
           | B of bool 
           | S of string 
    fun headR [] = raise Empty 
        | headR (R r :: _) = r 
        | headR _ = raise Domain 
    

    然後headR實際上並沒有接受任何類型。它只接受一個dynamic,它可以容納任意固定數量的具有任意類型參數的值構造函數。這個模擬異構列表:

    val foos = [R 42.0, I 10, B true, S "Hello, World!"] 
    
  • Using exceptions [informallyabstract.blogspot.com]:

    datatype dynamic = Dynamic of exn 
    exception IsReal of real 
    fun wrap_real r = Dynamic (IsReal r) 
    fun unwrap_real (Dynamic ex) = raise ex handle IsReal r => r 
    fun headR (d::_) = unwrap_real 
        | headR [] = raise Empty 
    

    headR然後同樣僅接受一個類型,dynamic,並且未能與該期間使用的任何異常,而不是的real包裝。使用異常和常規datatype定義之間的區別是異常可以在以後的新構造擴展:

    exception IsString of string 
    fun wrap_string r = Dynamic (IsString r) 
    fun unwrap_string (Dynamic ex) = raise ex handle IsString r => r 
    val foos = [wrap_real 42.0, wrap_string "This didn't exist before."] 
    

也不是可取的,因爲它們引入了運行時故障的不必要的風險。