2017-02-26 14 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 

我想請求

  • 編制原因如何更好地理解模式匹配如何工作。
  • 有沒有任何習慣寫法的函數?

例如:如果我想提取什麼聯繫到節點i,我想寫這樣的事情

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

有隻使用模式匹配任何方式檢查(= =)在非數字文字?

connected 0 (Link 0 j d) = (j,d)工作正常。但上面的例子不會。

回答

3

哈斯克爾只允許線性圖案,其中每個變量可以最多隻能出現一次。我相信這是一個故意的設計選擇。從理論上講

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

可以自動轉換爲

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

這意味着,非線性模式需要額外的Eq約束的各類非線性的變量。此外,有人可能會認爲,程序員有可能錯誤地重複使用一個變量,如果我們允許非線性模式,這個變量將被默默地忽略並導致意想不到的語義。

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 _ _)時聲明瞭兩個變量。這是不允許的。相反,你需要使用其他名稱和acclivity比較兩種:

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