3 回答

TA貢獻(xiàn)1811條經(jīng)驗(yàn) 獲得超4個(gè)贊
正如Lambdageek所建議的,這就是使用語(yǔ)義編輯器組合器(SEC)的方式。
首先是幾個(gè)有用的縮寫:
type Unop a = a -> a
type Lifter p q = Unop p -> Unop q
這Unop是一個(gè)“語(yǔ)義編輯器”,并且Lifter是語(yǔ)義編輯器的組合器。一些起重器:
onManager :: Lifter Coach BBTeam
onManager f (BBTeam n m p) = BBTeam n (f m) p
onDiet :: Lifter Diet Coach
onDiet f (Coach n c d) = Coach n c (f d)
onStakes :: Lifter Integer Diet
onStakes f (Diet n s e) = Diet n (f s) e
現(xiàn)在,只需簡(jiǎn)單地使SEC組成即可說(shuō)出您想要的內(nèi)容,即在(經(jīng)理)經(jīng)理的飲食中加1:
addManagerSteak :: Unop BBTeam
addManagerSteak = (onManager . onDiet . onStakes) (+1)
與SYB方法相比,SEC版本需要額外的工作來(lái)定義SEC,而我僅在此示例中提供了所需的內(nèi)容。SEC允許有針對(duì)性的應(yīng)用程序,如果玩家節(jié)食但我們不想對(duì)其進(jìn)行調(diào)整,這將很有幫助。也許還有一種很漂亮的SYB方法來(lái)處理這種區(qū)別。
編輯:這是基本SEC的替代樣式:
onManager :: Lifter Coach BBTeam
onManager f t = t { manager = f (manager t) }

TA貢獻(xiàn)1827條經(jīng)驗(yàn) 獲得超9個(gè)贊
稍后,您可能還需要看一下一些通用的編程庫(kù):當(dāng)數(shù)據(jù)的復(fù)雜性增加并且發(fā)現(xiàn)自己編寫了更多的樣板代碼(例如,增加了球員,教練的飲食和看守者的啤酒含量)時(shí),即使是不太冗長(zhǎng)的形式,也仍然是樣板。 SYB可能是最著名的庫(kù)(Haskell Platform附帶)。實(shí)際上,有關(guān)SYB的原始論文使用了非常相似的問(wèn)題來(lái)演示該方法:
考慮以下描述公司組織結(jié)構(gòu)的數(shù)據(jù)類型。公司分為部門。每個(gè)部門都有一個(gè)經(jīng)理,并且由一組子部門組成,其中一個(gè)部門可以是一個(gè)雇員或一個(gè)部門。經(jīng)理和普通雇員都是領(lǐng)薪的人。
[跳過(guò)]
現(xiàn)在假設(shè)我們想將公司中每個(gè)人的薪水提高指定的百分比。也就是說(shuō),我們必須編寫函數(shù):
增加::浮動(dòng)->公司->公司
(其余內(nèi)容在論文中-建議閱讀)
當(dāng)然,在您的示例中,您只需要訪問(wèn)/修改一個(gè)微小數(shù)據(jù)結(jié)構(gòu)的一部分,因此它不需要通用方法(仍然在下面為您的任務(wù)提供基于SYB的解決方案),但是一旦您看到重復(fù)的代碼/訪問(wèn)/模式您想檢查此修改或其他通用編程庫(kù)。
{-# LANGUAGE DeriveDataTypeable #-}
import Data.Generics
data BBTeam = BBTeam { teamname :: String,
manager :: Coach,
players :: [BBPlayer]} deriving (Show, Data, Typeable)
data Coach = Coach { coachname :: String,
favcussword :: String,
diet :: Diet } deriving (Show, Data, Typeable)
data Diet = Diet { dietname :: String,
steaks :: Integer,
eggs :: Integer} deriving (Show, Data, Typeable)
data BBPlayer = BBPlayer { playername :: String,
hits :: Integer,
era :: Double } deriving (Show, Data, Typeable)
incS d@(Diet _ s _) = d { steaks = s+1 }
addManagerSteak :: BBTeam -> BBTeam
addManagerSteak = everywhere (mkT incS)
- 3 回答
- 0 關(guān)注
- 405 瀏覽
添加回答
舉報(bào)