2017-10-20 9 views
0

任意のタイプのリストを取り、リストが実数のリストである場合にのみhead要素を返すサンプル関数を書きたいと思います。MLリストのタイプをチェックしてエラーマッサージを行う方法は?

これ以外の場合は、エラーメッセージ

が表示されます。 。 。オペレーターとオペランドはありません。 。 。

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:実数リスト=> hd x)'はどの型も*のリストを取るのではなく、実数のリストだけを取る。しかし、リストが実数*のリストである場合にのみhead要素を返し、実数のリストに従わない場合には型エラーを生成します。あるいは '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は、リストが空ではないが最初の要素に実数が含まれていない状況を説明しません。それから、別の例外が発生するはずです。

  • 次の要件は非常に疑わしいです。

    そうでない場合、関数はエラーメッセージ

    を与える必要があります。 。 。オペレーターとオペランドはありません。 。 。

    これは、実行時例外とコンパイル時エラーを区別しないことを示しています。これは、プログラムの起動後にエラーと例外がすべて処理される、動的に型指定された言語を使用したプログラミングの経験には徴候的です。

は、その後いくつかのアイデア:

リストの標準MLでは、彼らが唯一のコンパイルの型チェック段階で決定した時点で、1種類のものとすることができることを意味する、均質です。あなたはそれに対処し、よりダイナミックなタイピングを達成するためのいくつかの方法があります。

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

    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が実際にあらゆるタイプを受け付けません。それはちょうど1つを受け取ります、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

    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."] 
    

どちらも、彼らは、実行時の障害の不必要なリスクを紹介するので好適である:例外と定期datatype定義を使用しての違いは、例外が後で新しいコンストラクタを拡張することができるということではありません。

関連する問題