Нужна помощь в устранении путаницы с типами возвращаемых данных - PullRequest
0 голосов
/ 09 декабря 2011

У меня есть слишком сложная функция, чтобы я мог четко указать, какой должен быть тип функции.Я пытаюсь заставить 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 с.Ниже я определяю типы, с которыми я работаю.

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'

Хорошохорошо, похоже, все, что мне нужно сделать, это применить правильно размещенный конкат, и я могу заставить фактический тип GGHandler sub0 master0 monad0 [[Either UnFlaggedDay CalendarDay]] соответствовать ожидаемому типу GGHandler sub0 master0 monad0 [[Either UnFlaggedDay CalendarDay]]

Но подождите, не все так просто.Вот одна из многих попыток, и, независимо от того, где я размещаю конкат, кажется, что это приводит к одной и той же ошибке.

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

Обновление: эта проблема была решена только для выявления других (похожих) проблем.Я собираюсь воспользоваться советом, данным здесь, чтобы двигаться вперед с этим.

1 Ответ

3 голосов
/ 09 декабря 2011

Первый подозреваемый:

   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

?Да, и начнем с написания подписей типа.Это часто создает лучшие сообщения об ошибках.

...