Аргумент функции, кажется, исчезает при анализе типа - PullRequest
2 голосов
/ 28 марта 2020

Я пытаюсь сделать функцию generi c с использованием классов типов, и я постоянно сталкиваюсь с этой ошибкой:

У меня есть тип данных:

data ValeurM m = VLitteralM Litteral
               | VFonctionM (ValeurM m -> m (ValeurM m))

, который представляет либо функция, либо буквальное значение, m - это тип монады

У меня также есть класс инжектора для ввода значений в этот тип

class Injectable m t where
    injecte :: t -> ValeurM m

instance Injectable m Bool where
    injecte = VLitteralM . Bool

instance Injectable m Integer where
    injecte = VLitteralM . Entier

Я тогда пытался сделать функция ifthenelse обобщенным образом c, например:

injIf :: (Fail.MonadFail m) => (Bool -> ValeurM m -> ValeurM m -> ValeurM m) -> ValeurM m
injIf = injecte

ifM :: (Fail.MonadFail m) => Bool -> ValeurM m -> ValeurM m -> ValeurM m
ifM bool iss1 iss2 = if bool then iss1
                             else iss2

ifthenelseM :: (Fail.MonadFail m) => ValeurM m
ifthenelseM = injIf ifM

Однако я получаю следующее сообщение об ошибке:

Interprete.hs:595:9: error:
    • Could not deduce (Injectable
                          m (ValeurM m -> ValeurM m -> ValeurM m))
        arising from a use of ‘injecte’
        (maybe you haven't applied a function to enough arguments?)
      from the context: Fail.MonadFail m
        bound by the type signature for:
                   injIf :: forall (m :: * -> *).
                            Fail.MonadFail m =>
                            (Bool -> ValeurM m -> ValeurM m -> ValeurM m) -> ValeurM m
        at Interprete.hs:594:1-89
    • In the expression: injecte
      In an equation for ‘injIf’: injIf = injecte
    |
595 | injIf = injecte
    |         ^^^^^^^

Предполагается, что оно напоминает Нормализация по оценке , но я не могу заставить его работать

Что меня беспокоит, так это то, что сообщение об ошибке, похоже, не учитывает первый параметр Bool, я что-то упустил?

Сбой при компиляции

1 Ответ

2 голосов
/ 31 марта 2020

Этот экземпляр

instance (Monad m, Injectable m t) => Injectable m ((Bool -> ValeurM m -> ValeurM m -> ValeurM m) -> t) where
    injecte = injecte

- это не то, что вам нужно. В самом деле, он дает вам:

injecte :: ((Bool -> ValeurM m -> ValeurM m -> ValeurM m) -> t) -> ValeurM m

, но вы хотите

injIf :: (Bool -> ValeurM m -> ValeurM m -> ValeurM m) -> ValeurM m

, поэтому вместо него запускается экземпляр Bool -> t.

Вам может понадобиться экземпляр

instance {-# OVERLAPPING #-} (_TODO_)
  => Injectable m (Bool -> ValeurM m -> ValeurM m -> ValeurM m) where

, который перекрывается с Injectable m (Bool -> t), поэтому я добавил аннотацию {-# OVERLAPPING #-}.

В качестве альтернативы, возможно, вам нужна другая комбинация экземпляров, которая будет работать в сочетании с Injectable m (Bool -> t) instance

instance Injectable m t => Injectable m (ValeurM m -> t) where
instance Injectable m (ValeurM m) where  -- base case

На самом деле, это кажется лучшим решением. Вот реализация этих двух экземпляров; с этим я мог бы сделать ваш код скомпилированным:

instance (Monad m, Injectable m t) => Injectable m (ValeurM m -> t) where
    injecte f = VFonctionM (\v -> pure (injecte (f v)))

instance (Monad m) => Injectable m (ValeurM m) where
    injecte = id
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...