-1

Thx for the first Help. Now I changed this. but still a bog error. Is my whole Code wrong or just the part with the weekdays function. How can i call a function inside another function?

data Wochentag = Mo | Di | Mi | Do | Fr | Sa | So
deriving (Eq, Ord, Show, Enum)

data Month = Jan | Feb | März | April | Mai | Juni | Juli | Aug | Sep | Okt | Nov | Dec
deriving (Eq, Ord, Show, Enum)


weekday :: Integer -> Month -> Integer -> Wochentag
weekday day month year = weekdays day (zahlmonth month) year

y1 = year - (14 - zahlmonth) /12
x = y1 + (y1 /4) - (y1 /100) + (y1 /400)
m = zahlmonth + 12 * ((14- zahlmonth) /12) -2


weekdays day zahlmonth year
    | mod (day + x + ((31*m) / 12)) 7 == 0 = So
    | mod (day + x + ((31*m) / 12)) 7 == 1 = Mo
    | mod (day + x + ((31*m) / 12)) 7 == 2 = Di 
    | mod (day + x + ((31*m) / 12)) 7 == 3 = Mi 
    | mod (day + x + ((31*m) / 12)) 7 == 4 = Do 
    | mod (day + x + ((31*m) / 12)) 7 == 5 = Fr
    | mod (day + x + ((31*m) / 12)) 7 == 6 = Sa 
    | otherwise = error "kein Tag"



zahlmonth :: Month -> Integer
zahlmonth month = case month of
  Jan -> 1
  Feb -> 2
  März -> 3
  April -> 4
  Mai -> 5
  Juni -> 6
  Juli -> 7
  Aug -> 8
  Sep -> 9
  Okt -> 10
  Nov -> 11
  Dec -> 12

The error Log is:

 Couldn't match expected type `Month -> Integer'
                  with actual type `Integer'
    * In the first argument of `weekdays', namely `day'
      In the expression: weekdays day (zahlmonth month) year
      In an equation for `weekday':
          weekday day month year = weekdays day (zahlmonth month) year
   |
95 | weekday day month year = weekdays day (zahlmonth month) year
   |                                   ^^^

   Variable not in scope: year :: Month -> Integer
   |
97 | y1 = year - (14 - zahlmonth) /12
   |      ^^^^

Totally strange but have no idea how to fix it. When i give weekdays an description it becomes even worse.

M. Moz
  • 1
  • 2
  • You should always start your function by providing a type annotation, to declare your intent. Otherwise, GHC will infer the type of your functions, but in the case of a type error, GHC can not compare what it inferred and your intended type, producing only more vague error messages. – chi Dec 07 '17 at 08:35
  • I edited it now – M. Moz Dec 07 '17 at 09:21
  • What are these y1, x, m mean and where is `year` defined? – n. m. could be an AI Dec 07 '17 at 09:30
  • y1, x and m are from the gregorian way to calculate the day when given a date. year is the same Integer variable witch is given to weekday. – M. Moz Dec 07 '17 at 09:32
  • "from the gregorian way" Are they constants? What is their type? They are top level names, give them type annotations. Also, what does `(14 - zahlmonth)` mean? `zahlmonth` is a function of type `Month -> Integer`. – n. m. could be an AI Dec 07 '17 at 09:34
  • I think you maybe wanted to make y1, x, m parameters of some function(s), but as they stand now they are top level variables with cryptic names and unclear purpose. – n. m. could be an AI Dec 07 '17 at 09:38

1 Answers1

0

The issue here is that you did not add the types for all your top-level bindings, so some of them are being inferred to the wrong type. If only there were a type annotation, GHC would have reported the error immediately, but in absence of that, GHC has no way to see that the inferred type is wrong and so takes it at face value.

Much later on, the wrong type will cause issues, and only then GHC will report the problem -- on irrelevant code.

More in detail, here's what happens:

m = zahlmonth + ...

Here zahlmonth is a function Month -> Integer. Since the result type of + is the same of the arguments, m is also a function Month -> Integer.

Had m :: Integer been present, GHC would stop here with an error. But, alas, GHC can't know that this is the issue.

Then,

weekdays day zahlmonth year
    | mod (day + x + ((31*m) / 12)) 7 == 0 = So

Since the operations +,*,/ work on the same type, we get that day, x have the same type of m, i.e. Month -> Integer.

If weekdays had a type signature GHC would have spot the error, but without that it will happily carry on.

Finally,

weekday day month year = weekdays day (zahlmonth month) year

Here weekday has a signature, saying that day :: Integer. But above we inferred that weekdays expects day :: Month -> Integer. This triggers the type error

 Couldn't match expected type `Month -> Integer'
                  with actual type `Integer'
    * In the first argument of `weekdays', namely `day'

which is crystal clear, after one understands what's going on above during the inference.

The key point is that, however, ... understanding what's going on during the inference is not easy at all! In general, it is very hard to follow GHC in its auto-inferring of types around the program. Fortunately, this is not needed, provided one writes code carefully, annotating the types on the bindings, so that type errors can be caught as early as possible.

chi
  • 111,837
  • 3
  • 133
  • 218