我收集了大約十幾種我定義的類型的結構化東西(比如說Component
),其中每個都可以用「名稱」來標識,而且努力理清一個慣用的Haskell實例化和檢索方法。這些東西在我的應用程序中經常使用,因此概念上它們是一組全局常量或常量表,理想情況下這些常量將被初始化並保存以供快速檢索。Haskell成語,用於設置索引結構化值的集合
我目前的做法,我不舒服,只是使用一個函數來從它的名字「計算」每個Component
。
data Component = Component {
someData :: !String,
otherData :: ![Int]
} deriving Show
component :: Name -> Component
component n = case n of
-- about a dozen in the application
"1" -> Component "lasdkfj;alksdjfalkf" [1]
"Q" -> Component "nvjufhhqwe" [5,10,11]
"other" -> Component "ugugugu" []
"A" -> Component "alkkjsfkjaleifuhqiweufjc" []
"B" -> Component "randomletters" []
"C" -> Component "nothingimportant" [9,10]
"b" -> Component "uk" []
"c" -> Component "x" [4,2,7,9,0]
"" -> Component "ABC" []
-- if not listed above, the Component is computed
otherwise -> Component (someFunctionOf n) (someOtherFunctionOf n)
這不適合我。首先,Component
的名稱實際上是Component
的一部分,但不包含在該類型中。更重要的是,甚至可以計算常量值,但實際上它們只能在某個表中初始化。
考慮到這一點我也試過
type Name = String
import Data.Maybe
import Data.Map
data Component = Component {
name :: Name,
someDate :: String,
otherData :: [Int]
} deriving Show
components = fromList $ (\c -> (name c, c)) <$> [
Component "1" "lasdkfj;alksdjfalkf" [1],
Component "Q" "nvjufhhqwe" [5,10,11],
Component "other" "ugugugu" [],
Component "A" "alkkjsfkjaleifuhqiweufjc" [],
Component "B" "randomletters" [],
Component "C" "nothingimportant" [9,10],
Component "b" "uk" [],
Component "c" "x" [4,2,7,9,0],
Component "" "ABC" []
]
component :: Name -> Component
component n | isNothing c = Component n (someFunctionOf n) (someOtherFunctionOf n)
| otherwise = fromJust c
where c = Data.Map.lookup n components
這顯然已經處理了「常量」值作爲常量的優勢,但覺得尷尬,因爲它引入了一箇中間值(Map
components
)並在那裏複製名稱(在Component
中並作爲相應的鍵)。
無論如何,我覺得我正在解決這一切都是錯誤的,並且必須有更好的方法來建立一組索引結構化值,其中包括一堆常量和計算值。
優秀!你可以多說一點關於第二次導入的註釋('import Data.Map(Map)')。另外我想我需要'M.fromList'。是我的lambda生成'組件'好嗎?我確實「控制」了這一點,所以「名稱」的重複不是這樣的問題(正如您正確指出的那樣)。是否有Haskell成語來命名這種「私人」或「內部」值? – orome
@raxacoricofallapatorius(1)'import Data.Map(Map)'只是爲了讓類型簽名少一點噪音。離開它是完全可以的;它只意味着你必須編寫'components :: M.Map Name Component'。 (2)'M.fromList'的確如此。 (3)拉姆達很好。有一些無點的寫法,例如'liftA2(,)name id'('liftA2'在'Control.Applicative'中)和'name &&& id'('(&&&)'在'Control.Arrow '),但在這種情況下,選擇很大程度上是品味的問題(有些人會認爲免費版本更清晰,而其他人會覺得它們混淆)。 – duplode
@raxacoricofallapatorius(4)「是否有Haskell成語命名這樣的」私有「或」內部「值? - 不是真的;只要將它們命名爲其他名稱即可。這也意味着即使對於內部價值也要有合理清晰的名稱,以便人們更容易閱讀您的實施。此外,對於具有局部作用域的函數(函數參數,where子句定義等),使用較短和較少的描述性名稱通常是可以的,因爲在大多數情況下,有可能在快速瀏覽。 – duplode