下面定义的函数 mapRightR 仅更改地图的设置内容,而不更改键,并生成有效的Relation类型。
使用这个高级函数定义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 。
我尝试使用List而不是Set来定义Relation的另一个定义,它起作用了!
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
最佳答案
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
类型类所代表的)的endofunctor,而是一个函子,它将 Hask 实例类型与仅由实例组成的子类别映射Hask 。 (我认为我的描述正确无误;欢迎更正。)