我試圖從https://haskell-at-work.com/episodes/2018-01-19-domain-modelling-with-haskell-data-structures.html中洗掉 Database.sh 檔案中的 do 符號
但我有一個錯誤,我不知道為什么。(可能只是意味著我不了解 Haskell)
哈斯克爾代碼:
專案.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
[2 of 2] Compiling Database ( Database.hs, Database.o )
Database.hs:12:5: error: parse error on input `<$>'
|
12 | <$> (Sale . Money <$> getStdRandom (randomR (0, 4000)))
| ^^^
uj5u.com熱心網友回復:
這是一個簡單的縮進錯誤。
請記住, 的語法let <definitions> in <expr>允許存在多個定義塊。“A block of multiple things” 1基本上總是縮進在 Haskell 中很重要的背景關系,并且規則始終是塊中的每個“事物”必須從同一列開始,如果它們跨越多行,則繼續行都必須比塊的對齊列縮進更多。
這意味著這很好:
something = let foo = 1
bar = 2
baz = 3
in foo bar baz
因為f,b和b開始塊中的每個方程都let排在同一列。這也很好:
something = let
foo = 1
bar = 2
baz = 3
in foo bar baz
因為方程仍然精確排列。他們排列的位置實際上比關鍵字本身的縮進少let并不重要,in關鍵字是否進一步縮進也不重要。
但這很糟糕:
getTransactions :: ProjectId -> IO [Transaction]
getTransactions _ = let rtn = []
<$> (Sale . Money <$> getStdRandom (randomR (0, 4000)))
<*> (Purchase . Money <$> getStdRandom (randomR (0, 4000)))
in
pure rtn
因為里面的定義塊let 以. rtn = []作為第一個定義的一部分的所有內容都必須比rfrom進一步縮進rtn。要糾正它,您需要以下內容:
getTransactions :: ProjectId -> IO [Transaction]
getTransactions _ = let rtn = []
<$> (Sale . Money <$> getStdRandom (randomR (0, 4000)))
<*> (Purchase . Money <$> getStdRandom (randomR (0, 4000)))
in
pure rtn
您在哪里縮進以下幾行。或者(為了避免過度縮進)做這樣的事情:
getTransactions :: ProjectId -> IO [Transaction]
getTransactions _ =
let rtn = []
<$> (Sale . Money <$> getStdRandom (randomR (0, 4000)))
<*> (Purchase . Money <$> getStdRandom (randomR (0, 4000)))
in
pure rtn
有多種方法可以做到這一點;您也可以將=fromgetTransactions放在下一行,或者您可以將 thelet留在上一行,只rtn = []向下移動,等等。但是一旦您開始定義塊,您必須繼續規則,即所有內容都是條目的一部分在塊中必須進一步縮進;你不能在中間重新設定。
1 do塊有多個陳述句,let塊where有多個定義,case塊有多個分支,模塊有多個匯入和定義(通常我們在縮進級別 0 對齊這些,但您不必這樣做)等等。
其他任何內容的縮進都無關緊要,純粹是約定和可讀性的問題( aif/then/else的in一部分let/in,守衛或函式定義的其他部分等)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/462854.html
標籤:哈斯克尔
