2016-02-26 19 views
3

具有以下記錄:獲取記錄字段的文本表示?

data Sleep = Sleep 
    { _duration :: Maybe Int 
    , _drunk :: Bool 
    } 

有沒有辦法做到以下幾點:

deriveSomething ''Sleep 

fieldName duration :: String -- "duration" 

我需要這個類型安全DB特定領域的更新,即:

setField connection key duration (Just 50) 

它需要是DB不可知的(因此opaleye等)。

(如果可以用一個標準的包像lens更好的實現,但我沒能發現任何東西。)

+0

我認爲'序列化到JSON的時候也許你會發現有用在那裏 – epsilonhalbe

+0

@epsilonhalbe東西aeson'做類似的事情:看我下面的評論。 –

回答

2

可以使用Data.Data做到這一點:

{-# LANGUAGE DeriveDataTypeable #-} 
import Data.Data 

data Sleep = Sleep 
    { _duration :: Maybe Int 
    , _drunk :: Bool 
    } deriving (Typeable, Data) 

fieldNames :: Data a => a -> [String] 
fieldNames = constrFields . toConstr 

例子:

> fieldNames (Sleep undefined undefined) 
["_duration", "_drunk"] 

您必須決定如何將名稱轉換爲數據庫列後,但這應該相當容易。

這需要使用特殊的構造函數創建一個值時,請記住,數據類型可以有很多的構造函數。是不是真的有解決的辦法,但你可以有類似

sleepFieldNames :: [String] 
sleepFieldNames = fieldNames (Sleep undefined undefined) 

,這樣你就不必保持重新計算它。

+0

側面說明:你需要'{ - #語言DeriveDataTypeable# - }',使這項工作 – epsilonhalbe

+0

不幸的是,我需要一個文字表述爲每一個具體* *領域,不可能一下子所有領域,即我真的需要這樣的東西' fieldName :: Field - > String',其中'Field'以某種方式從數據類型定義派生。 –

+0

@PhilipKamenarsky我不知道如果沒有寫一些TemplateHaskell,這是否可能。 GHC實際上只將你的訪問器看作函數,你真正得到的是'data Sleep = Sleep(Maybe Int)Bool; _duration ::睡眠 - >也許Int; _drunk :: Sleep - > Bool',只需訪問您的位置即可。還有一些額外的魔法在發生,但是如果沒有一些TH爲你生成'duration'作爲一些'Field'類型(可能是某種帶標記的Lens?),你將無法做到。 – bheklilr

相關問題