2013-10-04 42 views
5

我檢查有沒有一些現行做法模板哈斯克爾/鏡頭的一些花式處理的簡單情況:當前最佳實踐有關記錄的全球命名空間

data Person = Person { 
    name :: String, 
    ... 
} 

data Company = Company { 
    name :: String, 
    ... 
} 

目前我避免通過限定導入來污染全局名稱空間,但它確實使記錄訪問笨拙。

import Person as P 

isFred :: Person -> Bool 
isFred p = (P.name p) == "Fred" 

真的還有沒有更好的方式來訪問記錄字段?


我接受@Emmanuel Touzery的答案,因爲有用的鏈接到另一個問題覆蓋相同的理由。另一個問題沒有出現在「haskell命名空間」的搜索上。其他答案沒有錯,但我只能接受這個答案。

這裏提到的解決方案使用模板Haskell,透鏡,類型等等,基本上爲每個字段「HasName」使用單個函數「name」創建一個類型類型。然後,每個數據類型都是具有自己實現的那個類的一個實例。然後有一些我不完全明白的魔法允許不同類型的參與。

對於任何想知道這一切的Haskell新手來說,這是因爲記錄基本上是元組,其中的字段選擇器實現爲普通函數,選擇(例如)該元組的第二個元素。如果您導出這些字段選擇器函數,那麼它們將位於全局名稱空間中,遲早(通常較早)會發生衝突。

所以 - 你要麼限定進口(如我上面的例子),要麼嘗試提出不衝突的名字(在名稱前面加上最好的希望)。

鏡頭的東西是所有的憤怒截至2013年,並允許字段選擇器/ getters + setter等組成。鏡頭的基本思想不是太複雜,但實施正好在我的頭上。


爲了記錄(哈哈!)我覺得在其他職位的解決方案可能是我後,但它確實涉及大量魔法(5個擴展只是假記錄命名空間)。

回答

2

類似的問題已經問過了,你可以看到一個答案在這裏提示鏡頭: https://stackoverflow.com/a/17488365/516188

眼下隱形眼鏡處於哈斯克爾社區一大熱門詞彙,他們肯定有他們的用途,和他們可能是長期解決這個命名空間問題的一部分。但目前使用鏡頭來解決這個問題的人會是我認爲的少數人。正如Nikita Volkov所說的那樣,在這一點上,合格的進口和前綴將是典型的解決方案。

更新:發現約this other option還沒有最終確定,但似乎promessing。這裏在this blog post的末尾提到。

6

一般只有兩種辦法,但遺憾的是沒有關於他們在社區consesus:

  1. 將您的記錄與反對他們的功能在不同的文件,並使用它們合格完整的別名,如:

    import qualified Data.Person as Person; import Data.Person (Person) 
    
    isFred :: Person -> Bool 
    isFred p = (Person.name p) == "Fred" 
    

    考慮這種方法與像Java這樣的語言相同,其中文件只包含一個類。

  2. 將您在同一個文件中的記錄,而與之前的記錄的名稱字段名稱,例如:

    data Person = Person { 
        personName :: String, 
        personAge :: Int, 
        ... 
    } 
    

鏡片的庫的方法都沒有這個問題。

+0

這些都沒有真正解決這個問題。這只是不同類型的前綴。這在OO中不是問題,因爲方法/屬性的名稱空間僅限於類/對象 - 通常只是全局的類名稱空間。無論如何感謝 - 我能找到的最後一次討論大約是18個月大。 –

+1

關於實施更好的記錄系統的談判一直如此。有幾十種建議的解決方案。甚至有[Haskell方言,解決問題](http://en.wikipedia.org/wiki/Frege_(programming_language)#Records)。不幸的是,我們只能等待其中的任何一項實施。 –

+0

是的 - 我已經瀏覽了一些較老的(在我頭上)的討論。它有這樣一種感覺,即我們將在十年後等待100%的解決方案,而不是幾年前的90%解決方案。 –

0

這是我的方法。在實踐中,我發現我並不經常需要導出記錄名稱,所以命名空間污染只是模塊本身的一個問題。所以我用一個短的前綴,通常是類型類的第一個字母,就像這樣:

data Person = Person { 
    pName :: String, 
    ... 
} 

data Company = Company { 
    cName :: String, 
    ... 
} 

在我需要讓其他模塊直接訪問場的情況下,通常只有一個或兩個字段。通常我只想讓讀取權限。所以在這種情況下,我可能會有點創意,也許是這樣的。

module Whatever 
    { 
    Person, 
    personName, 
    Company, 
    companyName, 
    ... 
    } 

data Person = Person { 
    pName :: String, 
    ... 
} 

data Company = Company { 
    cName :: String, 
    ... 
} 

personName :: Person -> String 
personName = pName 

companyName :: Company -> String 
companyName = cName 
+0

是的,你總是可以在字段名稱的前面。以使Haskell記錄不符合外部結構和醜化代碼爲代價來避免這個問題。 –