0

我有一个函数太复杂,无法明确说明函数类型应该是什么。我试图让 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] 我开始遍历列表,将一些UnFlaggedDays 转换为CalendarDays。其他函数将转换UnFlaggedDays 的其余部分。下面我定义了我正在使用的类型。

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 }

你看到那里发生了什么吗?这是我所做的更改。我在传递processedDaysconcat之前传递给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)'

更新:这个问题已经解决了,只是为了揭示其他(类似的)问题。我将接受这里给出的建议以继续前进。

4

1 回答 1

3

第一个嫌疑人:

   case (L.null match) of
      True -> do
           processedDays <- ([(Left $ MkUFD day)] :) <$> flagScheduled rest
           return processedDays

也许应该读

   case (L.null match) of
      True -> do
           processedDays <- ((Left $ MkUFD day) :) <$> flagScheduled rest
           return processedDays

? 哦,从编写类型签名开始。这通常会产生更好的错误消息。

于 2011-12-08T20:35:41.303 回答