我认为您应该直接研究结构合理的数据。首先,定义一些数据类型来帮助你解决问题。
type ID = Int
data Account = Account {idno::ID,
name :: String,
balance :: Int,
password :: String} deriving (Read,Show)
如果你愿意,你可以选择不同的类型。这使您可以定义函数,例如
sameID :: ID -> Account -> Bool
sameID anID account = idno account == anID
注意数据标签idno
也是一个方便的功能Account -> ID
。我们应该使用一些样本数据进行测试:
sampleData = [Account 385634 "Fred" 234 "Iluvw1lm4",
Account 405382 "Barney" (-23) "pebbles",
Account 453464 "Wilma" 1432 "c4r3fu1n355 br33d5 pr0sp3r:ty"]
我们可以使用它来测试功能(并推断 Barney 对密码安全或财务管理一无所知)。
现在您需要决定是Data.Map
使用他们的 ID 还是列表来存储您的帐户。列表更容易从文件中读取,但地图更容易查找。所以要么这样做:
type Accounts = [Account]
或使用地图:
import qualified Data.Map as Map -- Put this at the top of the file if so.
type Accounts = Map.Map ID Account
无论哪种方式,您都需要
findUserByID :: Accounts -> ID -> Maybe Account
findUserByID = undefined -- you can work this out
如果您使用的是地图,则需要找到它。要么浏览文档——无论如何都是一个好计划,要么使用hoogle 搜索引擎来找到它。如果您不确定,您可以 hoogle for Map ID Account -> Maybe Account
,虽然它会警告您它不知道 ID 或 Account,但您需要的功能就在那里!你最好搜索一下,Map id account -> Maybe account
这样它就知道它可以使用一般功能。
如果您正在使用列表,则需要filter
在列表中添加一个函数,该函数在 ID 匹配时为您提供 true,否则为 false:sameID
这会有所帮助。
你还需要
updateByID :: ID -> Account -> Accounts -> Accounts
updateByID anId newaccount = undefined -- you can work this out too
但更有用的是
updateUsingID :: Account -> Accounts -> Accounts
updateUsingID acc = updateByID (idno acc) acc
如果您使用的是地图,那将很容易,但如果您使用的是列表,则需要使用map
类似的功能
onlyChange :: Account -> (Account -> Account)
onlyChange newacc acc | idno acc == idno newacc = newacc
| otherwise = acc
你可以定义
showAccount :: Account -> String
showAccount acc = undefined -- use the functions, eg name acc ++ ....
-- or just use show
和功能
changePassword :: String -> Account -> Account
changePassword newpwd acc = acc {password = newpwd}
使用里面的想法changePassword
和函数balance
,你应该可以写
changeBalance :: (Int -> Int) -> Account -> Account
changeBalance = undefined -- you try
然后你可以写
pay :: Int -> Account -> Account -> (Account,Account)
pay amount fromAcc toAcc = undefined
提示:使用changeBalance (+ amount)
and changeBalance (subtract amount)
。
最后你需要
updateTwoUsingID :: (Account,Account) -> Accounts -> Accounts
updateTwoUsingID (new1,new2) = updateUsingID new1 . updateUsingID new2
我忍不住要告诉你那个,因为它是函数组合的一个很好的例子。
如果您发现很难使用这些Maybe Account
东西,请忽略它直到最后,就像我们忽略文件 IO 直到最后一样。fmap
使用和之类的函数>>=
非常方便Maybe
。查找它们,或者现在完全放弃 Maybe 并使用 hard error
s。(例如!
,在 Map 中给出错误而不是 Nothing。)也许比运行时错误更好,但也许你现在可以摆脱错误。
有一些粘合在一起要做,然后一些文件输入/输出要做。对于文件输入/输出,read
在show
您的Accounts
.
您不必这样做 - 这只是一种方法。(好吧,两个,如果你把列表和地图算作两种方法。)玩得开心!