为什么在此Functor的类实例中不能接受这种保留结构的“ fmap”?

时间:2019-05-23 18:57:25

标签: haskell

下面定义的功能 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

我尝试了使用Relation的另一种定义,即使用 List 而不是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 个答案:

答案 0 :(得分:11)

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类型类表示的)的终结者,而是一个函子,它将仅由具有Ord实例的类型组成的 Hask 子类别映射为 Hask 。 (我认为我的描述正确无误;欢迎更正。)