2012-08-01 61 views
1

我想在編譯時創建映射,將編譯時間鍵映射到運行時間值。如果不是所有必需的鍵都存在,函數應該能夠檢查這些鍵並拋出編譯器錯誤。編譯時間鍵 - >值映射

這大概想什麼,我來實現:

class HasFirst a 
    first :: String 

class HasMiddle a 
    middle :: String 

class HasLast a 
    last :: String 

print_full_name :: (HasFirst a, HasLast a) => a -> String 

addFirst :: String -> a -> b 
addFirst s x = -- (Add a first name to x) 

emptyName :: -- some empty name 

x1 = addFirst "John" $ addLast "Smith" $ emptyName 
x2 = addMiddle "Bob" $ addLast "Smith" $ emptyName 

main = putStr $ print_full_name x1 -- Compiles 
main = putStr $ print_full_name x2 -- No first name so compile error 

對於那些使用C++的知識,我想大概是什麼boost::fusion::map一樣。

我不需要上面的代碼,什麼是重要的,我可以在編譯時檢查參數。無論機制是類還是別的,我都不介意。

有沒有這樣做的包裝還是很容易發展呢?

+0

我不明白;你能舉一個你如何使用它的例子嗎? – 2012-08-01 07:48:50

+0

編譯時映射必須將編譯時鍵映射到編譯時值,否?我誤解你想要什麼嗎? – dave4420 2012-08-01 07:56:10

+0

我已經在我的問題 – Clinton 2012-08-01 08:01:26

回答

7

讓我告訴你,你怎麼能得到您例如使用稱爲phantom types功能設計技術工作:

{-# LANGUAGE EmptyDataDecls #-} 

data YES 
data NO 

data Name first middle last = Name String String String 

emptyName :: Name NO NO NO 
emptyName = Name "" "" "" 

addFirst :: String -> Name first middle last -> Name YES middle last 
addFirst s (Name a b c) = Name s b c 

addMiddle :: String -> Name first middle last -> Name first YES last 
addMiddle s (Name a b c) = Name a s c 

addLast :: String -> Name first middle last -> Name first middle YES 
addLast s (Name a b c) = Name a b s 

printFullName :: Name YES middle YES -> String 
printFullName (Name a b c) = a++b++c 

我們使用的Name三個類型的參數來跟蹤其名字已被設定。 printFullName只接受名字和姓氏。當試圖打印underdefined名字我們得到一個類型錯誤:

*Main> printFullName $ addFirst "John" $ addLast "Smith" $ emptyName 
"JohnSmith" 
*Main> printFullName $ addFirst "John" $ addMiddle "Edward" $ emptyName 

<interactive>:1:16: 
    Couldn't match expected type `YES' against inferred type `NO' 
     Expected type: Name YES YES YES 
     Inferred type: Name YES YES NO 
    In the second argument of `($)', namely 
     `addFirst "John" $ addMiddle "Edward" $ emptyName' 
    In the expression: 
      printFullName $ addFirst "John" $ addMiddle "Edward" $ emptyName 

注意,這是一個非常粗略的編碼,但希望它演示了幻像類型的力量。

0

這聽起來像是一個OOHaskell的應用程序。