Obecnie uczę się Haskell i próbuję zrozumieć, jak ocenia się typki i jak działają let
i where
. Ten kod działa poprawnie:Ocena, niech i gdzie w Haskell
{-# LANGUAGE FlexibleInstances #-}
class Expr a where
literal :: Integer -> a
instance Expr Integer where
literal = id
instance Expr [Integer] where
literal i = [i]
coerceInteger :: Integer -> Integer
coerceInteger = id
main = print $ coerceInteger (literal 100) : literal 100 -- Prints [100,100]
ale zmieniając główną funkcję do
main = print $ coerceInteger expr : expr
where expr = literal 200
powoduje błąd kompilatora:
Couldn't match expected type `[Integer]' with actual type `Integer'
In the second argument of `(:)', namely `expr'
In the second argument of `($)', namely `coerceInteger expr : expr'
In the expression: print $ coerceInteger expr : expr
Zgaduję, to dlatego, że w pierwszym main
metodzie literal 100
jest oceniany dwa razy, podczas gdy w drugim przykładzie literal 200
jest oceniany tylko raz, więc kompilator jest zmuszony wybrać typ.
Jak mogę uwzględnić ten kod, aby uniknąć powtórzenia się, nie powodując tego błędu? Próbowałem używać let expr = literal 300 in ...
, ale wpadłem na ten sam problem.