我有一个函数太复杂,无法明确说明函数类型应该是什么。我试图让 GHC 同意我所期望的就是它所期望的。首先,功能,我认为它应该做什么。然后,混乱出现在哪里。
flagScheduled ((Left (MkUFD day)):rest) = do
match <- runDB $ selectList [TestStartDate ==. Just day,
TestStatus /<-. [Passed,Failed]] []
case (L.null match) of
True -> do
processedDays <- ([(Left $ MkUFD day)] :) <$> flagScheduled rest
return processedDays
False -> do
let flaggedRange = (calcFlagged match)
product = (testFirmware . snd . P.head) match
processedDays <- (flagScheduled'
([(Left $ MkUFD day)] ++
(L.take flaggedRange) rest) (show product) :) <$>
(flagScheduled . L.drop flaggedRange) rest
return processedDays
flagScheduled ((Right day):rest) = do
processedDays <- ((Right $ day):) <$> flagScheduled rest
return processedDays
flagScheduled _ = return []
calcFlagged (( _ ,(Test _ _ (Just startDate) (Just endDate) _ _ )) : rest) =
fromIntegral $ C.diffDays endDate startDate
flagScheduled' toBeFlagged product =
L.map (flagIt product) toBeFlagged
where flagIt product (Left (MkUFD day)) = Right $
MkCal $
Right $
MkUAD $
Left $
MkSDay day
(read product :: Product)
Reserved
这个想法是我从一个[Either UnFlaggedDay CalendarDay]
我开始遍历列表,将一些UnFlaggedDay
s 转换为CalendarDay
s。其他函数将转换UnFlaggedDay
s 的其余部分。下面我定义了我正在使用的类型。
newtype AvailableDay = MkAD (Text, C.Day)
deriving (Show, Eq)
newtype UnAvailableDay = MkUAD (Either ScheduledDay Out_Of_Office)
deriving Show
data ScheduledDay = MkSDay C.Day Product ScheduledState
deriving Show
newtype ReservedDay = MkRDay (C.Day,Product)
deriving (Ord,Show,Eq,Read)
newtype ASAPDay = MkADay (C.Day,Product)
deriving (Ord,Show,Eq,Read)
newtype UnFlaggedDay = MkUFD C.Day
newtype CalendarDay = MkCal (Either AvailableDay UnAvailableDay)
deriving Show
所以这就是问题所在,当我编译时出现这个错误,这本身并不令人困惑。
Utils/BuildDateList.hs:173:44:
Couldn't match expected type `Either a0 b0'
with actual type `[Either UnFlaggedDay CalendarDay]'
Expected type: GGHandler sub0 master0 monad0 [Either a0 b0]
Actual type: GGHandler
sub0 master0 monad0 [[Either UnFlaggedDay CalendarDay]]
In the return type of a call of `flagScheduled'
In the second argument of `(<$>)', namely `flagScheduled rest'
好的,看起来我需要做的就是应用一个放置良好的 concat,我可以使实际类型GGHandler
sub0 master0 monad0 [[Either UnFlaggedDay CalendarDay]]
与预期类型匹配GGHandler
sub0 master0 monad0 [[Either UnFlaggedDay CalendarDay]]
但是等等,没那么简单。这是许多尝试中的一种,无论我将 concat 放在哪里,它似乎都会导致相同的错误。
Utils/BuildDateList.hs:164:16:
Couldn't match expected type `[Either UnFlaggedDay b0]'
with actual type `Either UnFlaggedDay b0'
Expected type: GGHandler
sub0 master0 monad0 [[Either UnFlaggedDay b0]]
Actual type: GGHandler
sub0 master0 monad0 [Either UnFlaggedDay b0]
In the expression: return $ P.concat processedDays
In the expression:
do { processedDays <- ([(Left $ MkUFD day)] :)
<$>
flagScheduled rest;
return $ P.concat processedDays }
你看到那里发生了什么吗?这是我所做的更改。我在传递processedDays
给concat
之前传递给return
。
flagScheduled ((Left (MkUFD day)):rest) = do
match <- runDB $ selectList [TestStartDate ==. Just day,
TestStatus /<-. [Passed,Failed]] []
case (L.null match) of
True -> do
processedDays <- ([(Left $ MkUFD day)] :) <$> flagScheduled rest
return $ P.concat processedDays
False -> do
let flaggedRange = (calcFlagged match)
product = (testFirmware . snd . P.head) match
processedDays <- (flagScheduled'
([(Left $ MkUFD day)] ++
(L.take flaggedRange) rest) (show product) :) <$>
(flagScheduled . L.drop flaggedRange) rest
return $ P.concat processedDays
flagScheduled ((Right day):rest) = do
processedDays <- ((Right $ day):) <$> flagScheduled rest
return $ P.concat processedDays
flagScheduled _ = return []
因此,看起来像直截了当的更改却并非如此的事实向我表明,我并不真正了解问题所在。有任何想法吗?
更新:我做了丹尼尔建议的更改,但收到此错误:
Utils/BuildDateList.hs:169:37:
Couldn't match expected type `[Either UnFlaggedDay t0]'
with actual type `Either UnFlaggedDay b0'
In the first argument of `(++)', namely `(Left $ MkUFD day)'
In the first argument of `flagScheduled'', namely
`((Left $ MkUFD day) ++ (P.take flaggedRange) rest)'
In the first argument of `(:)', namely
`flagScheduled'
((Left $ MkUFD day) ++ (P.take flaggedRange) rest) (show product)'
更新:这个问题已经解决了,只是为了揭示其他(类似的)问题。我将接受这里给出的建议以继续前进。