所以我有一个Database.Persist.TH模型定义如下:
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Transaction json
date Day
payee String
categoryId Int
memo String
outflow Double
inflow Double
deriving Show Generic
|]
我正在尝试编写一个函数来计算给定[Transaction]
的帐户的余额。
到目前为止,我已推断出以下内容:
calculateBalance :: [Transaction] -> Transaction -> Double
calculateBalance [Transaction{..}] = foldr(\x -> transactionInflow - transactionOutflow) (+)
这就是说,我认为,我们正在使用foldr接收交易列表 - 这意味着列表将会解构"对于每个单独的事务,将在两个双精度之间执行减法,并返回Double
。
然而,我所做的事情似乎是错误的。
一个这样的错误是:
Couldn't match type ‘Transaction’ with ‘t0 a0’
Expected type: Transaction -> Double
Actual type: t0 a0 -> Double
In the expression:
foldr (\ x -> transactionInflow - transactionOutflow) (+)
In an equation for ‘calculateBalance’:
calculateBalance [Transaction {..}]
= foldr (\ x -> transactionInflow - transactionOutflow) (+)
然而,更改calculateBalance :: [Transaction] -> t0 Transaction -> Double
似乎没有解决问题,calculateBalance :: [Transaction] -> Transaction -> t0 Transaction -> Double
也没有,所以我对如何处理感到有些困惑。
我可能做错了什么?任何其他提示,使这"惯用" Haskell也将非常感激。
答案 0 :(得分:2)
出错的原因是您只对单个元素列表进行事务分解,并提供两个函数作为foldr
的参数。
calculateBalance = foldr (\t acc -> acc + transactionInflow t - transactionOutflow t) 0
现在我开会了 - 我会在一两个小时内解释一下。
首先是的,你是正确的,你的功能的类型签名是不正确的。
在下文中,我将假设正确的类型签名是
calculateBalance :: [Transaction] -> Double
因为你写了。
我正在尝试编写一个函数来计算给定
的帐户的余额[Transaction]
首先是
calculateBalance [Transaction{..}] =
仅匹配单例列表,transactionInflow
扩展名提供的transactionOutflow
和RecordWildCards
仅匹配左侧的值。所以“折叠功能”实际上是一个不变的。
接下来是折叠函数有错误的类型/被应用于错误的参数。 foldr
foldr :: (a -> b -> b) -> b -> [a] -> b
所以第一个参数是2个参数的函数,然后初始累加器值出现,然后需要列表。
函数参数:
(\t acc -> transactionInflow t - transactionOutflow t + acc)
Transaction
的记录创建了可以从transactionInflow/transactionOutflow
中提取Double
- 值的函数t :: Transaction
。我不认为你可以在lambda表达式中使用RecordWildCards
,这样可以省去你输入的t
,我认为这不是一个大问题(如果你想要你可以在{{中提取函数定义) 1}}子句,这很少是一个坏主意。)
然后你需要累加器值,它由给定顶级函数签名的类型约束专门用于let/where
(即必须与最终结果相同)。
Double
注意:如果您查看calculateBalance = foldr aux 0
where aux Transaction{..} acc = acc + transactionInflow - transactionOutflow
中foldr
的{{1}}的类型签名,则Data.List
晚于4.8,
base
这是由Foldable-Traversable-Proposal (FTP)引起的,并且是我上面列出的那个的推广,但对于foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
,它的行为完全相同。