爲newtypes的主要用途是:
- 用於定義類型的替代實例。
- 文檔。
- 數據/格式正確性保證。
我正在研究一個應用程序,現在我廣泛使用newtypes。 Haskell中的newtypes
是純粹的編譯時間概念。例如。用下面的解包器編譯成與「x」相同的代碼,unFilename (Filename "x")
。運行時間絕對爲零。有data
類型。這是實現上述目標的一個非常好的方法。
-- | A file name (not a file path).
newtype Filename = Filename { unFilename :: String }
deriving (Show,Eq)
我不想不小心將此視爲文件路徑。這不是文件路徑。這是數據庫中某個概念文件的名稱。
對於算法來說,正確的事物是非常重要的,newtypes可以幫助解決這個問題。這對安全性也非常重要,例如,考慮將文件上傳到Web應用程序。我有這幾種:
-- | A sanitized (safe) filename.
newtype SanitizedFilename =
SanitizedFilename { unSafe :: String } deriving Show
-- | Unique, sanitized filename.
newtype UniqueFilename =
UniqueFilename { unUnique :: SanitizedFilename } deriving Show
-- | An uploaded file.
data File = File {
file_name :: String --^Uploaded file.
,file_location :: UniqueFilename --^Saved location.
,file_type :: String --^File type.
} deriving (Show)
假設我有這個功能,從一個已經上傳的文件清理的文件名:
-- | Sanitize a filename for saving to upload directory.
sanitizeFilename :: String --^Arbitrary filename.
-> SanitizedFilename --^Sanitized filename.
sanitizeFilename = SanitizedFilename . filter ok where
ok c = isDigit c || isLetter c || elem c "-_."
從我生成一個唯一的文件名現在:
-- | Generate a unique filename.
uniqueFilename :: SanitizedFilename --^Sanitized filename.
-> IO UniqueFilename --^Unique filename.
從任意文件名生成一個唯一的文件名是很危險的,它應該首先被消毒。同樣,一個唯一的文件名因此通過擴展總是安全的。我現在可以將文件保存到磁盤,並將該文件名放在我的數據庫中,如果我想。
但它也可能很煩人,必須包裝/解開很多。從長遠來看,我認爲這是值得的,特別是爲了避免價值不匹配。 ViewPatterns有所幫助:
-- | Get the form fields for a form.
formFields :: ConferenceId -> Controller [Field]
formFields (unConferenceId -> cid) = getFields where
... code using cid ..
也許你會說,在一個函數展開這是一個問題 - 如果你傳遞cid
到錯誤的功能?不是一個問題,使用會議ID的所有功能都將使用ConferenceId類型。出現的是一種在編譯時被強制執行的功能級功能合同系統。很不錯。所以是的,我儘可能經常使用它,特別是在大型系統中。
Hrm ...看起來像我不能標記多個答案接受。我希望能以某種方式接受關於這個問題的不同意見的合理表示...... – StevenC 2009-06-17 03:58:21