2017-02-26 5 views
0
{-# LANGUAGE NamedFieldPuns #-} 

data Factory = Factory { fId :: Int} 
data Link = Link Int Int Double 

hasLinkTo :: Factory -> Link -> Bool 
hasLinkTo Factory{fId} (Link fId _ _) = True 

ガットエラーNamedFieldPunsは、パターンは

• Conflicting definitions for ‘fId’ Bound at: <source.hs> In an equation for ‘hasLinkTo’ 
私はそれを修正することができ、変数を使用して知っている

、変数名を使用して一致する

hasLinkTo Factory{fId=a} (Link b _ _) = a == b 

私は

  • をお願いしたいです編集の理由パターンマッチングの仕組みをよりよく理解するためにilを使用します。
  • 関数を記述するための慣用方法はありますか?例えば

:私はこの

connected :: Int -> Link -> (Int, Double) 
connected i (Link i j d) = (j,d) 
connected i (Link j i d) = (j,d) 

のようなものを書きたいノードiにどのようなリンク、抽出したい場合(==)かどうかを確認する方法はありますのみパターンマッチングを使用して非数値リテラルでは?

connected 0 (Link 0 j d) = (j,d)は問題なく動作しています。上記の例はそうではありません。

答えて

3

Haskellは唯一の各変数は、最高1回出現することができ、線形パターンを、ことができます。私はこれが意図的なデザインの選択だと信じています。理論的に

case e1 of C x x y -> e2 ; ... 

を言えば、自動的に非直線的パターンは非線形変数の型のための追加Eq制約が必要であることを意味します

case e1 of C x1 x2 y | x1==x2 -> e2 ; ... 

これに変換することができます。さらに、プログラマが間違って変数を誤って再利用する可能性があると主張することもできます。これは、非線形パターンを許可すれば、静かに無視され、意図しないセマンティクスにつながります。

はおそらく、Haskellの設計者はパターンに| x1==x2を追加すると、あまりにも面倒ではなかったことを感じたとの意図がより明確になります。数値リテラルの場合

は、しかし、彼らはこの翻訳を続けました。パターン

case e1 of K 0 y z -> e2 ; ... 

case e1 of K x y z | x==0 -> e2 ; ... 

に変換しないとEqを必要としません。 0は変数ではないため、非線形パターンの問題はなくなりました。

とにかく、慣用的な方法は、| x1==x2のようなガードをノンライナーパターンに追加することです。 この時点でパターンマッチングのみを使用することはできません。

1

Factory{fId}での記録のパンニングは、GHCがFactory{fId=fId}に拡大する構文的唯一の砂糖です。これはfIdという名前の変数をFactoryレコードのfIdというフィールドの値で宣言しました。

さらに、パターンマッチングは変数のみを宣言します。同じ名前を繰り返して比較することはできません。

eq a a = True 
eq _ _ = False 

これは、同じことをやろうとした簡単な例です。しかし、それはコンパイルされません。

同様に、(Link fId _ _)を実行するときに2つの変数を宣言するので、コンパイラは不平を言います。これは許可されていません。代わりに、別の名前を使用する必要があると上り坂が2を比較:

hasLinkTo Factory{fId} (Link fInd' _ _) = fId == fId'