就我個人而言,我會去RecordWildCards
並稱它爲一天。但是,這是另一個有趣的方式,在某些情況下可能會很有用:謹慎風,使用動態類型來獲得改變類型的摺疊!
{-# LANGUAGE DeriveDataTypeable #-}
import Data.Dynamic (dynApp, fromDynamic, toDyn)
import Data.List (foldl')
import Data.Typeable (Typeable)
-- Add the 'Typeable' instance to enable runtime type information.
data Zone = Zone
{ zId, zOwnerId, zPodsP0, zPodsP1, zPodsP2, zPodsP3 :: Int
} deriving (Show, Typeable)
mkZone :: [String] -> Maybe Zone
mkZone = fromDynamic . foldl' dynApp (toDyn Zone) . map (toDyn . readInt)
where
-- This type-specialised 'read' avoids an ambiguous type.
readInt :: String -> Int
readInt = read
這將啓動類型從Zone
構造,:
Int -> Int -> Int -> Int -> Int -> Int -> Zone
然後相繼其應用於每個Int
從輸入讀取,改變它的類型:
Int -> Int -> Int -> Int -> Int -> Zone
Int -> Int -> Int -> Int -> Zone
Int -> Int -> Int -> Zone
Int -> Int -> Zone
Int -> Zone
Zone
而且它的工作原理:
> mkZone ["1", "2", "3", "4", "5", "6"]
Just (Zone {zId = 1, zOwnerId = 2, zPodsP0 = 3, zPodsP1 = 4, zPodsP2 = 5, zPodsP3 = 6})
如果提供的參數太少,你會得到Nothing
因爲運行時轉換失敗:
> mkZone ["1", "2", "3", "4", "5"]
Nothing
不過,如果你提供太多許多參數,你會得到一個異常:
> mkZone ["1", "2", "3", "4", "5", "6", "7"]
*** Exception: Type error in dynamic application.
Can't apply function <<Zone>> to argument <<Int>>
這是很容易通過使用dynApply
而不是dynApp
來修復,其返回Maybe
而不是拋出。而且只要你在Maybe
正在工作,你還不如用Text.Read.readMaybe
處理分析錯誤:
{-# LANGUAGE DeriveDataTypeable #-}
import Control.Monad ((<=<))
import Data.Dynamic (Dynamic, dynApply, fromDynamic, toDyn)
import Data.List (foldl')
import Data.Typeable (Typeable)
import Text.Read (readMaybe)
data Zone = Zone { … } deriving (Show, Typeable)
mkZone :: [String] -> Maybe Zone
mkZone = fromDynamic <=< foldl' go (Just (toDyn Zone)) . map readInt
where
go :: Maybe Dynamic -> Maybe Int -> Maybe Dynamic
go mAcc mx = do
acc <- mAcc
x <- mx
dynApply acc $ toDyn x
readInt :: String -> Maybe Int
readInt = readMaybe
真正雖然,可能不這樣做。