2012-02-24 26 views
4

私はこれを次のようにしていますintroduction to Haskell、この特定の場所(ユーザー定義型2.2)は特にわかりにくいです。要するに、私はコードのどの部分がコードであり、どの部分が著者の考えであるかを理解していません。 (Ptとは何ですか - どこにも定義されていませんか?)言うまでもなく、実行/コンパイルできません。intと文字列のどちらかを含む型を作成します。

私が理解しやすくする例として、IntegerとStringのペア、またはStringとIntegerのペアですが、他のものは定義しませんでした。それを使用することになり

理論的な機能は非常に次のようになります。ここでは

(defgeneric combine (a b) 
    (:documentation "Combines strings and integers")) 

(defmethod combine ((a string) (b integer)) 
    (concatenate 'string a (write-to-string b))) 

(defmethod combine ((a integer) (b string)) 
    (concatenate 'string (write-to-string a) b)) 

(combine 100 "500") 
+1

'Pt'は' Point a'データ型のコンストラクタです。すなわち、a型の2つの値をとり、それらを 'Pt'で囲む関数a-> a->点aである。 'data'宣言は私にとっては自然な感じです.LHSでは名前(およびもしあればパラメータ)を与え、RHSではこの型が取り得る値を列挙します。 – Vitus

答えて

8

です:

combine :: StringIntPair -> String 
combine a b = (show a) ++ b 
combine a b = a ++ (show b) 

あなたが作業コードが必要な場合は、同じことをその、ここでそれを行うためのCLコードをですデータ型を定義するための一つの方法:私は2 Cを定義した

data StringIntPair = StringInt String Int | 
        IntString Int String 
    deriving (Show, Eq, Ord) 

注意コンパイラはタイプStringIntPairで、StringIntIntStringです。 combineの定義で今

combine :: StringIntPair -> String 
combine (StringInt s i) = s ++ (show i) 
combine (IntString i s) = (show i) ++ s 

私はコンストラクタと一致し、正しい行動を選択するために、をマッチングパターンを使用しています。

*Main> let y = StringInt "abc" 123 
*Main> let z = IntString 789 "a string" 
*Main> combine y 
"abc123" 
*Main> combine z 
"789a string" 
*Main> :t y 
y :: StringIntPair 
*Main> :t z 
z :: StringIntPair 

例について注意すべきいくつかのこと:ここで

は、使い方の例をいくつか挙げます

  • StringIntPairタイプです。インタプリタで:t <expression>を行うと式
  • StringIntIntStringの種類を示す垂直バー(|)はコンストラクタ
  • よく書かれた関数は、そのそれぞれのコンストラクタと一致する必要が分離同じタイプのコンストラクタ
  • あります引数の型。私は2つのパターン、各コンストラクタの1
+2

@wvxvwはい、コンストラクタを定義する必要があります! 'data StringIntPair = StringInt String Int'では、**' StringInt String Int' **は 'String'と' Int'の2つの引数を取るコンストラクタです。私はあなたの2番目の質問を完全に理解しているかどうかわかりません。あなたはより完全な答えを得るためにそれを別の質問として投稿したいかもしれません。 –

+3

ハスケルのデータコンストラクタは**何も**何もしません。 (これはC++やJavaのコンストラクタとはまったく異なります)。これは、他の束のデータと区別するために、たくさんのデータを叩くだけのタグです。 'StringInt" abc "123"は 'StringInt'でタグ付けされた' String'と 'Int'です。 –

7
data StringIntPair = StringInt String Int 
        | IntString Int String 

combine :: StringIntPair -> String 
combine (StringInt s i) = s ++ (show i) 
combine (IntString i s) = (show i) ++ s 

combineを書いた理由は、だから、そのように使用することができます:Haskellのは、強く型付けされ

> combine $ StringInt "asdf" 3 
"asdf3" 
> combine $ IntString 4 "fasdf" 
"4fasdf" 
3

ので、あなたはいつもどのような種類を知っています変数は持っています。さらに、あなたはもっと知りません。たとえば、リストの長さを計算する関数lengthを考えてみましょう。

length :: [a] -> Int 

a任意の(すべての要素が同じタイプを有するが)戻るとIntのリストを取り、である:それはタイプを有しています。この関数は、リストノードの1つを見て、そこに格納されているものを調べることは決してできません。なぜなら、格納されているものについてどのような情報も取得できていないためです。これは、Javaのような典型的なOOP言語とは対照的に、実行時に型情報を格納する必要がないため、Haskellを非常に効率的にします。

1つのパラメータに異なる種類の変数を設定できるようにするには、代数データ型(ADT)を使用できます。一つは、店舗のいずれかStringIntまたはIntStringは次のように定義することができ:

data StringIntPair = StringInt String Int 
        | IntString Int String 

次の2つのどのパラメータにをマッチングパターンによって取られて見つけることができます。 (文字列とinの両方がADTにカプセル化されているので、1つしかないことに注意してください):

combine :: StringIntPair -> String 
combine (StringInt str int) = str ++ show int 
combine (IntString int str) = show int ++ str 
+0

@wvxvw:関数アプリケーション(「スペース」、並置演算子とも呼ばれます)は左結合であり、最も密接に結び付けられます。さもなければ、Haskellはインフィニクス演算子の優越性と結合性を設定することができます( 'infix'、' infixr'または 'infixl'の後に0から9までの数字が続きます;固定性宣言とも呼ばれます)。関数のアプリケーションは 'infixl 10'、' ++ 'は' infixr 5'と考えることができます。あなたがわからない場合は、GHCiを使って( ':i ++ 'をタイプする)、接頭辞表記を使うことができます('(++)str(show int) ') – Vitus

+1

@wvxvw:探しているなら単純なルールですが、関数アプリケーションはどんな演算子よりも緊密に束縛されていることを覚えておいてください。つまり、 'ab#cd'は常に'(ab)#(cd) 'です。あなたはあまりにも多くの優先順位を暗記する必要はありません。 – hammar

関連する問題