2016-05-19 2 views
3

多項式リングをリングから外すファンクタを作成しようとしています。私の基本的なタイプ、Ring_eltは、次のシグネチャがあります。私の多項式ファンクタがどのように見えるファンクタのOCaml構文エラー

module type Ring_elt = sig 
    type t 
    val add : t -> t -> t 
    val mul : t -> t -> t 
    val zer : t 
    val one : t 
    val neg : t -> t 
end;; 

module Make_Poly2(Underlying:Ring_elt) = struct 
    type t = Poly of Underlying.t list 
    let rec create lst = 
    match List.rev lst with 
    | Underlying.zer :: tl -> create List.rev tl 
    | _     -> Poly of lst 
end;; 

(そう「作成」機能は、その後、リストを取る先頭のゼロを削除し、必要があります結果の多項式を返します)。しかし、私は構文エラーを取得し、utopは "基礎"の後ろに "zer"を強調します。

は比較すると、(整数の多項式を作るための)次のコードは動作します:

module Make_int_poly = struct 
    type t = Poly of int list 
    let rec create lst = 
    match List.rev lst with 
    | 0 :: tl -> create (List.rev tl) 
    | _  -> Poly lst 
end;; 

何が起こっているすべてのアイデア?

+1

構文エラー 'Poly of lst'とタイプエラー' create List.rev tl'(2つ目の例では両方とも修正されています)を編集する必要があります。 – Lhooq

+0

ありがとうございます。他の構文エラーと速くてゆるいことを謝罪します。 –

+0

'List.rev lst with ... :: tl - > ... List.rev tl'は、リストの最後の要素を取得するのに非効率的な方法です(リスト全体を再構築しているので2回)。むしろ、関数last:リスト - >オプションaを作成します。先行ゼロを削除するには(リストの最初の0のように)、関数 'dropWhile:( 'a - > bool) - >'リスト - > 'リスト'を[これとは異なりません] https://hackage.haskell.org/package/base-4.8.2.0/docs/Data-List.html#v:dropWhile)。 –

答えて

1

ジェフリーの答えは良いのですが、代わりにif建設とそれを修正するの、何をやるべきことは以下の通りです:代数的データ型を使用

代わりの

val zer : t 
val one : t 

を書くあなたは

を書くことができ
module type Ring_elt = sig 
    type t = Zer | One | Num of t 
    val add : t -> t -> t 
    val mul : t -> t -> t 
    val neg : t -> t 
end 

module Make_int_poly = struct 
    type t = Poly of int list 
    let rec create lst = 
    match List.rev lst with 
    | Underlying.Zer :: tl -> create (List.rev tl) 
    | _     -> Poly lst 
end 

パターンを簡単に作成できるため、はるかに良い方法ですその上で一致し、あなたのタイプにいくつかの定数を追加することも問題なしでtです。

+0

答えをありがとう。定数と代数データ型に関する簡単な質問:一度ZerとOneの定数を追加すると、例えば、基礎となる型が標準構造の整数である場合、コンパイラに強制的に'int 0 'を見て' Zer 'を見ますか? –

+0

「Num Zero」と「One」は異なる数字で表現されているようですが、Num(Num Zero)やNum Oneなどのように、この特定の代数型は少し曖昧です。 0と1のパターンコンストラクタを持つ方が便利です。つまり、署名の一部として 'val is_zer:t - > bool'を抽象化の利点を追加して持たせることもできます。 –

+0

@SimonShineさて、 't'型をプライベート(シグネチャ内)として定義すると、適切な関数で' t'型の値を作成することしかできません。したがって、たとえばNum(Num Zero)を作成することは不可能です。そして、「Num Zero」と「One」は同じではありませんか?私は、1つは0、もう1つは1であることを意味します:-D – Lhooq

2

OCamlパターンは、定数、データコンストラクタ、およびパターンマッチングによってバインドされた新しい名前から構築されます。 Underlying.zerはそのようなものではありません。しかし0がその一つです。

ifと入力してUnderlying.zerと比較してみましょう。

+0

はい、 'Underlying.zer'は有効な値コンストラクタですが、' 0'とは異なり、有効なパターンコンストラクタではありません。 –

+0

ジェレミースコフィールドと@シモンシャイン、答えとコメントの両方に感謝します。これらはまさに私が慣れることを望んでいるocamlの癖のようなものです。私は上記のLhooqの答えを受け入れていますが、すべての回答は良いものです。 –

+0

@JohnBinder:はい。私はパターンコンストラクタを奇妙なものとして考えたことはありませんでしたが、代数的データ型定義が値コンストラクタだけでなく、値デストラクタ(パターンコンストラクタ)を作成し、組み込みの値リテラルが両方としてダビングすることを最初に学んだのは驚くべきことでした。実際にコンパイル時に知られている値だけが、パターンマッチングのコストを予測可能な低レベルに保つためのパターンとして機能するようなものでなければなりません。 (実行時に生成された値が有効なパターンであった場合、 '='を使用して構造的な等価性を実行する予測不可能なコストに終わる可能性があります。) –