Haskell 从 do 符号传递到 Applicative(第 2 部分)
Haskell Passing from do notation to Applicative (Part 2)
我正在尝试从 https://haskell-at-work.com/episodes/2018-01-19-domain-modelling-with-haskell-data-structures.html
中删除 Database.sh 文件中的 do 符号
但是我有一个错误,我不知道为什么。 (可能只是表示我不知道 Haskell)
这是
的延续
Haskell代码:
Project.hs
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Project where
import Data.Text (Text)
newtype Money = Money
{ unMoney :: Double
} deriving (Show, Eq, Num)
newtype ProjectId = ProjectId
{ unProjectId :: Int
} deriving (Show, Eq, Num)
data Project
= Project ProjectId
Text
| ProjectGroup Text
[Project]
deriving (Show, Eq)
data Budget = Budget
{ budgetIncome :: Money
, budgetExpenditure :: Money
} deriving (Show, Eq)
data Transaction
= Sale Money
| Purchase Money
deriving (Eq, Show)
数据库
import System.Random (getStdRandom, randomR)
import Project
getBudget :: ProjectId -> IO Budget
getBudget _ = Budget
<$> (Money <$> getStdRandom (randomR (0, 10000)))
<*> (Money <$> getStdRandom (randomR (0, 10000)))
getTransactions :: ProjectId -> IO [Transaction]
getTransactions _ =
let rtn = []
<$> (Sale . Money <$> getStdRandom (randomR (0, 4000)))
<*> (Purchase . Money <$> getStdRandom (randomR (0, 4000)))
in
pure rtn
错误
在运行之后stack ghc Database.hs --package random
Database.hs:12:13: error:
* Couldn't match expected type: Transaction -> Transaction -> b
with actual type: [a0]
* In the first argument of `(<$>)', namely `[]'
In the first argument of `(<*>)', namely
`[] <$> (Sale . Money <$> getStdRandom (randomR (0, 4000)))'
In the expression:
[] <$> (Sale . Money <$> getStdRandom (randomR (0, 4000)))
<*> (Purchase . Money <$> getStdRandom (randomR (0, 4000)))
* Relevant bindings include rtn :: f b (bound at Database.hs:12:7)
|
12 | let rtn = []
| ^^
在
let rtn = []
<$> (Sale . Money <$> getStdRandom (randomR (0, 4000)))
<*> (Purchase . Money <$> getStdRandom (randomR (0, 4000)))
您似乎在尝试列出这两个操作的结果?这是行不通的,因为 (<$>)
的第一个参数必须是函数,而 []
不是函数(还有其他原因)。如果你想保留这个符号,你应该用配对函数替换:
pair x y = [x, y]
然后
let rtn = pair <$> ...
但我真的认为这里合适的组合器是 sequenceA
sequenceA :: (Applicative f) => [f a] -> f [a]
它接受一个动作列表,并返回一个动作return一个结果列表。
所以:
let rtn = sequenceA [Sale . Money <$> getStdRandom (randomR (0, 4000)),
Purchase . Money <$> getStdRandom (randomR (0, 4000))]
哦,不应该有pure
到return这个。已经是正确的类型了,不需要提升成IO
.
顺便说一句,getStdRandom . randomR
也称为 randomRIO
。
我正在尝试从 https://haskell-at-work.com/episodes/2018-01-19-domain-modelling-with-haskell-data-structures.html
中删除 Database.sh 文件中的 do 符号但是我有一个错误,我不知道为什么。 (可能只是表示我不知道 Haskell)
这是
Haskell代码:
Project.hs
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Project where
import Data.Text (Text)
newtype Money = Money
{ unMoney :: Double
} deriving (Show, Eq, Num)
newtype ProjectId = ProjectId
{ unProjectId :: Int
} deriving (Show, Eq, Num)
data Project
= Project ProjectId
Text
| ProjectGroup Text
[Project]
deriving (Show, Eq)
data Budget = Budget
{ budgetIncome :: Money
, budgetExpenditure :: Money
} deriving (Show, Eq)
data Transaction
= Sale Money
| Purchase Money
deriving (Eq, Show)
数据库
import System.Random (getStdRandom, randomR)
import Project
getBudget :: ProjectId -> IO Budget
getBudget _ = Budget
<$> (Money <$> getStdRandom (randomR (0, 10000)))
<*> (Money <$> getStdRandom (randomR (0, 10000)))
getTransactions :: ProjectId -> IO [Transaction]
getTransactions _ =
let rtn = []
<$> (Sale . Money <$> getStdRandom (randomR (0, 4000)))
<*> (Purchase . Money <$> getStdRandom (randomR (0, 4000)))
in
pure rtn
错误
在运行之后stack ghc Database.hs --package random
Database.hs:12:13: error:
* Couldn't match expected type: Transaction -> Transaction -> b
with actual type: [a0]
* In the first argument of `(<$>)', namely `[]'
In the first argument of `(<*>)', namely
`[] <$> (Sale . Money <$> getStdRandom (randomR (0, 4000)))'
In the expression:
[] <$> (Sale . Money <$> getStdRandom (randomR (0, 4000)))
<*> (Purchase . Money <$> getStdRandom (randomR (0, 4000)))
* Relevant bindings include rtn :: f b (bound at Database.hs:12:7)
|
12 | let rtn = []
| ^^
在
let rtn = []
<$> (Sale . Money <$> getStdRandom (randomR (0, 4000)))
<*> (Purchase . Money <$> getStdRandom (randomR (0, 4000)))
您似乎在尝试列出这两个操作的结果?这是行不通的,因为 (<$>)
的第一个参数必须是函数,而 []
不是函数(还有其他原因)。如果你想保留这个符号,你应该用配对函数替换:
pair x y = [x, y]
然后
let rtn = pair <$> ...
但我真的认为这里合适的组合器是 sequenceA
sequenceA :: (Applicative f) => [f a] -> f [a]
它接受一个动作列表,并返回一个动作return一个结果列表。
所以:
let rtn = sequenceA [Sale . Money <$> getStdRandom (randomR (0, 4000)),
Purchase . Money <$> getStdRandom (randomR (0, 4000))]
哦,不应该有pure
到return这个。已经是正确的类型了,不需要提升成IO
.
顺便说一句,getStdRandom . randomR
也称为 randomRIO
。