2016-12-13 10 views
3

私はハスケルには新鮮で、いくつかのコードを書いて言語を理解しようとしています。私はghciに関する非常に簡単な説明だけに精通しています:頭、尾、和、(*)など - 非常に簡単です。ハスケルで「制約」が意味するもの

私が作ろうとしている機能は、任意の次元数のベクトルに対するピタゴラスの定理を解くためのものです。これは次のようになります:平方根(a^2 + b^2 + c^2 ...)

私はghciでいくつかの行で行うことができますが、私は関数を作ろうとしています:私はそれを実行しようとすると、

mod :: [Num a] => a 
mod x = sqrt a 
    where a = sum [b] 
      where [b] = map sq [x] 

私は問題を理解していない:

sq x = x*x 

b = map sq [1,2,3] 

a = sum b 

x = sqrt b 

私はこれを行うと、私は多くの種類の署名を含めるようにしようと、 現在、私の関数は次のようになります。

Expected a constraint, but ‘[Num a]’ has kind ‘*’ 
    • In the type signature: 
     Main.mod :: [Num a] => a 

答えて

9

調整するためのいくつかのこと:それは標準ライブラリからモジュロ関数の名前であるとして

0)modは、あなたの関数のための良い名前ではありません。代わりにnormと呼んでいます。

1)あなたが書くことを意図型シグネチャは次のとおりです。

norm :: Num a => [a] -> a 

[a]はタイプaの要素を持つリストのタイプです。 =>の前のNum aはタイプではなく、という制約があり、aは数値型(またはより正確にはNumクラスのインスタンスである必要があります)であることが指定されています。 [Num a] =>は、大括弧を使用しているため、型チェッカーは制約の代わりにリスト型を使用しようとしているため、あなたが見たエラーにつながります。

Num a問題を超えて、署名から結果の種類を除外しました。修正された署名は、関数が数値のリストを取り、数値を返すことを反映しています。

2)Num aの制約は、実行しようとするものに対して弱すぎます。 sqrtを使用するためには、単なる数値型を持っている必要がありますが、Floatingのインスタンスである1(この回答への参照leftaroundaboutさんのコメント):

GHCi> :t sqrt 
sqrt :: Floating a => a -> a 

したがって、あなたの署名は

する必要があります
norm :: Floating a => [a] -> a 

3)[x]は、単一の要素を持つリストで、xです。あなたの引数がすでにリストである場合、型シグニチャが示すように、角括弧で囲む必要はありません。あなたの関数は、それから、次のようになります。

norm :: Floating a => [a] -> a 
norm x = sqrt a 
    where a = sum b 
      where b = map sq x 

それとも、もっときれいに、二where - ブロックなし:あなたが認識しているとおり

norm :: Floating a => [a] -> a 
norm x = sqrt (sum b) 
    where b = map sq x 
+1

FTR:名前にもかかわらず、 'Floating'が本当に' RealFloat'(またはだろう「浮動小数点数のクラス」、ではありません['IEEE'](http://hackage.haskell.org/package/ieee754-0.7.9/docs/Numeric-IEEE.html#t:IEEE)でも可能です。これは単純に、式with_を行うことができる_number型のクラスであり、厳密な実数演算のようなものを可能にします。 – leftaroundabout

+0

@leftaroundaboutそれを強調してくれてありがとう。不正確なステートメントが削除されました。 – duplode

0

短い答えは[Num a]が制約ではないということです。 (Num a)またはNum aと書く必要があります。クラスアサーションが tyvar形態qtyclsを有し、そしてタイプtyvarのメンバーシップを表すクラスアサーション及びコンテキストの構文

context → class 
    | (class1 , … , classn)   (n ≥ 0) 
class → qtycls tyvar 
    | qtycls (tyvar atype1 … atypen) (n ≥ 1) 
qtycls → [ modid . ] tycls 
tycls → conid 
tyvar → varid 

Haskell 2010 Language Report

4.1.3から

クラス内qtycls。クラス識別子は大文字で始まります。 コンテキストがゼロ以上のクラスのアサーションから成り、C1一般的な形態(...、Cnの未C1のU1など)を有し、...、Cnのは、クラス識別子であり、U1の各...、UNは、型変数、または1つ以上の型への変数型のアプリケーションです。 n = 1の場合、外側のカッコを省略することができます。一般的に、我々は、コンテキストを示すためにCXを使用して、我々は、コンテキストCXによって制限型トンを示すCX => Tを書き込みます。コンテキストcxには、で参照される型変数が含まれている必要があります。です。便宜上、コンテキストcxが空であっても、具体的な構文には=>が含まれていませんが、cx => tと記述します。

4

、値はそのタイプによって分類することができます。 "foo"Just 'c'等、Maybe Charを入力同様

を有し、[Char]を入力した、タイプは、それら種類によって分類することができます。値を指定できる具体的な型は、すべて*です。

> :k Int 
Int :: * 
> :k Maybe Int 
Maybe Int :: * 

タイプのコンストラクタにも種類があります:あなたは、これはGHCiの中:kコマンドを使用して見ることができます。基本的に型評価関数なので、その種類は正規関数に似ています。

> :t id 
id :: a -> a 
> :k Maybe 
Maybe :: * -> * 

Num aとは何ですか?タイプではないので、種別は*ではありません。これは型コンストラクタではないので、矢印の種類はありません。それは新しいものなので、それを記述するために新しい種類が作られました。

> :k Num Int 
Num Int :: Constraint 

そしてNum自体はConstraint -valued機能である:それは一種*の値をとり、Constraintを生成します。

> :k Num 
Num :: * -> Constraint 

種類Constraintのあるものは、特定の型クラスを指定するために使用されます型はのインスタンスでなければなりません。これは、型シグニチャの=>より前に発生する可能性のある値です。また、instance「機能」を「引数」である:

instance Num Int where 
    ... 
関連する問題