需要帮助清除与返回类型的混淆

时间:2011-12-08 20:20:13

标签: haskell yesod

我有一个函数太复杂了,我无法明确函数类型应该是什么。我正在努力让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转换为CalendarDay s。 其他函数将转换UnFlaggedDay的其余部分。下面我定义了我正在使用的类型。

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 []

事实上,看起来像是一个没有直接变化的事实,向我表明我并不真正理解问题是什么。有什么想法吗?

更新:我做了Daniel建议的更改,但收到了这个错误:

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)'

更新:此问题已解决,只是为了揭示其他(类似)问题。我将采取这里给出的建议继续推进。

1 个答案:

答案 0 :(得分: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

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