Понимание того, как Either является экземпляром Functor

В свободное время я изучаю Haskell, так что это вопрос для начинающих.

] В своих чтениях я наткнулся на пример, иллюстрирующий, как Либо становится экземпляром Functor :

instance Functor (Either a) where
    fmap f (Right x) = Right (f x)
    fmap f (Left x) = Left x

Теперь я пытаюсь понять, почему реализация отображается в случае конструктора значения Right , но не в случае Left ?

Вот мое понимание:

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

instance Functor (Either a) where
    fmap g (Right x) = Right (g x)
    fmap g (Left x) = Left x

Теперь:

  1. Я знаю, что fmap :: (c -> d) -> fc -> fd

  2. , если мы заменим f на Либо a , мы получим fmap :: (c -> d) -> Либо ac -> Либо ad

  3. тип of Right (gx) равно Либо a (gx) , а тип gx - d , поэтому мы имеем, что тип of Right (gx) is Either ad , чего мы и ожидаем от fmap (см. 2. выше)

  4. , если мы посмотрим на Left (gx) , мы можем использовать те же рассуждения, чтобы сказать, что его тип Либо (gx) b , то есть Либо db , что не то, что мы ожидаем из fmap (см. 2. выше): d должен быть вторым параметром, а не первым! Поэтому мы не можем сопоставить Left . public: class Message {/*...*/}; typedef int (* Обратный вызов) (Сообщение * msg); void registerCallback (int msgclass, Callback f); } ...

    РЕДАКТИРОВАТЬ: МОТИВАЦИЯ

    Предположим, я определяю класс обработчика как

    class Handler {
    public:
      class Message { /*...*/ };
      typedef int (*Callback)(Message *msg);
      void registerCallback(int msgclass, Callback f);
    };
    

    Клиент может выполнять

    int f1(Handler::Message *msg)
    { /* handle message */ }
    
    int f2(Handler::Message *msg)
    { /* handle message */ }
    
    int main(){
      Handler h;
      h.registerCallback(1, f1);
      h.registerCallback(2, f2);
      // ....
    }
    

    Компилятор действительно проверяет, что f1 и f2 подходят в качестве параметров для registerCallback , однако клиент должен правильно определить f1 и f2 . Поскольку у меня уже есть typedef ed Callback , я бы хотел, чтобы клиент мог использовать его вместо этого.

    END EDIT

    Я бы хотел что-то сделать примерно так:

    typedef int arithmetic(int i, int j);
    
    arithmetic sum
    {
     return i+j;
    }
    
    arithmetic max
    {
      return (i>j)? i:j;
    }
    // etc.
    

    Однако оба

    arithmetic sum
    arithmetic sum()
    

    не компилируются, а также этот

    arithmetic sum(int i, int j)
    

    , который дает ошибку компилятора

    func.cpp: 4: error: 'sum' объявлено как функция, возвращающая функцию

    Причина, по которой я хочу это, заключается в том, что я хочу иметь класс Handler , который предоставил бы typedef для функции обратного вызова, которую он принимает, включая список параметров .

6
задан davka 4 March 2011 в 16:25
поделиться