Почему этот сохраняющий структуру "fmap" не может быть принят в экземпляре класса этого Functor? - PullRequest
3 голосов
/ 23 мая 2019

Определенная ниже функция mapRightR изменяет только установленное содержимое карты, а не ключи, и создает действительный тип отношения.

Действительно ли невозможно использовать эту высокоуровневую функцию для определения экземпляра Functor Relation, или моя реализация неверна.

{-# LANGUAGE GADTs #-}

import Data.Map as M
import Data.Set as S

data Relation a b where
    R :: (Ord a, Ord b) => Map a (Set b) -> Relation a b

instance Functor Relation where
    fmap f r = mapRightR f r

mapRightR :: Ord b1 => (b2 -> b1) -> Relation a b2 -> Relation a b1
mapRightR f (R r) = R $ M.map (S.map f) r

Спасибо, chepner .

Я попробовал другое определение отношения, используя Список вместо Set, и оно работает!

data Relation a b where
    R :: (Ord a) => Map a [b] -> Relation a b

instance Functor (Relation a) where
    fmap f r = mapRightR f r

mapRightR :: (b2 -> b1) -> Relation a b2 -> Relation a b1
mapRightR f (R r) = R $ M.map (L.map f) r

1 Ответ

11 голосов
/ 23 мая 2019

mapRightR ограничен, он не будет работать для любого типа b, поскольку fmap требует:

-- Specialized for f ~ Relation c
fmap ::               (a -> b) -> Relation c a -> Relation c b

, но

mapRightR :: Ord b => (a -> b) -> Relation c a -> Relation c b

В более категоричных терминах Relation c - это не конечный функтор, который отображает Hask на Hask (это то, что представляет класс типов Functor), а скорее функтор, который отображаетподкатегория Hask , состоящая только из типов с Ord экземплярами до Hask .(Я думаю, что я охарактеризовал это правильно; исправления приветствуются.)

...