{-# LANGUAGE GADTs #-}
module Main where
data CudaExpr x where
C :: x -> CudaExpr x
Add :: Num x => CudaExpr x -> CudaExpr x -> CudaExpr x
Sub :: Num x => CudaExpr x -> CudaExpr x -> CudaExpr x
Mul :: Num x => CudaExpr x -> CudaExpr x -> CudaExpr x
Div :: (Num x, Fractional x) => CudaExpr x -> CudaExpr x -> CudaExpr x
Eq :: (Eq x) => CudaExpr x -> CudaExpr x -> CudaExpr Bool
-- LessThan :: CudaExpr x -> CudaExpr x -> CudaExpr Bool
-- If :: CudaExpr Bool -> CudaExpr x -> CudaExpr x -> CudaExpr x
eval (C x) = x
eval (Add a b) = eval a + eval b
eval (Sub a b) = eval a - eval b
eval (Mul a b) = eval a * eval b
eval (Div a b) = eval a/eval b
eval (Eq a b) = eval a == eval b
-- eval (LessThan a b) = eval a < eval b
-- eval (If cond true false) = if eval cond then eval true else eval false
main :: IO()
main = print "Hello"
Это не похоже на ограничение мономорфизма. Это то, что ошибка я получаю:Почему случай Eq (GADT) дает мне ошибку типа?
* Could not deduce: x ~ Bool
from the context: (t ~ Bool, Eq x)
bound by a pattern with constructor:
Eq :: forall x. Eq x => CudaExpr x -> CudaExpr x -> CudaExpr Bool,
in an equation for `eval'
at app\Main.hs:23:7-12
`x' is a rigid type variable bound by
a pattern with constructor:
Eq :: forall x. Eq x => CudaExpr x -> CudaExpr x -> CudaExpr Bool,
in an equation for `eval'
at app\Main.hs:23:7
Expected type: CudaExpr x -> Bool
Actual type: CudaExpr t -> t
* In the first argument of `(==)', namely `eval a'
In the expression: eval a == eval b
In an equation for `eval': eval (Eq a b) = eval a == eval b
* Relevant bindings include
b :: CudaExpr x (bound at app\Main.hs:23:12)
a :: CudaExpr x (bound at app\Main.hs:23:10)
Что бы вы сказали, что тип возврата 'eval' есть? Это не может быть 'Num x => x', потому что' eval (Eq (C 3) (C 3)) 'должен возвращать' True :: Bool'. Это не может быть 'Bool', потому что' eval (Add (C 3) (C 3)) 'должен возвращать' 6 :: Num x => x'. – chepner
Ну, очевидно, это должно зависеть от структуры CudaExpr, переданной в функции. Я не понимаю, почему это не должно быть тем или иным. Я знаю, что приведенный выше пример можно кодировать с использованием фантомных типов, так же как и ограничения типа typeclass, которые я задал здесь? ... Нет, даже если я прокомментирую все случаи, но 'Eq' все еще не работает. –
Хорошо, я понял. В конце концов, это было похоже на ограничение мономоризма. Когда я добавлю аннотацию типа 'eval :: CudaExpr x -> x', ошибка исчезнет. Спасибо за подсказку. –