在下限總是小于或等于上限的情況下,如何保持范圍類型的類型不變量

我試圖用以下定義對泛型Range類型建模:

data Range a = Range
  { lower :: a
  , upper :: a }

我添加了一個智能構造函數(并且只導出了它而沒有數據構造函數),這樣消費者就不會意外地創建一個Range,其lower字段大于upper字段:

range :: Ord a => a -> a -> Range a
range lower upper =
  if lower > upper
  then Range upper lower
  else Range lower upper

這一切都很好,我繼續推導它的Functor實例:

instance Functor Range where
  fmap f (Range lower upper) = Range (f lower) (f upper)

這成了問題,因為我可以:

main :: IO ()
main = do
  let r1 = range 1 2
      r2 = fmap negate r1
  return ()
  -- Now r2 has its upper field less than its lower field

我天真的嘗試是在fmap的實現中使用智能構造函數range,如:

instance Functor Range where
  fmap f (Range lower upper) = range (f lower) (f upper)

但是,它不會編譯,因為f lowerf upper不受約束,只有一個Ord a實例。

如何修復這個問題,從而保持lower始終小于或等于upper的類型不變量?

? 最佳回答:

正如在評論中提到的,沒有辦法使它成為合法的函子,因為fmap f必須適用于所有函數f,即使結果類型沒有Ord實例。

在我看來,你有兩個很好的選擇:


首先:不要定義函子約束,使用更受限制的類型創建一個新函數rangeMap(set就是這樣做的)。

data Range a = Range { lower :: a, higher :: a } deriving Show

range :: Ord a => a -> a -> Range a
range lower upper =
  if lower > upper
  then Range upper lower
  else Range lower upper

rangeMap :: Ord b => (a -> b) -> Range a -> Range b
rangeMap f (Range x1 x2) = range (f x1) (f x2)
rangeMap (negate) $ range 2 1 
Range {lower = -2, higher = -1}

第二,更改范圍的表示,使其支持Functor實例,但將lowerhigher實現為需要Ord約束的函數。

data Range a = Range a a

instance Functor Range where
  fmap f (Range x1 x2) = Range (f x1) (f x2)

lower :: Ord a => Range a -> a
lower (Range x1 x2) = min x1 x2

higher :: Ord a => Range a -> a
higher (Range x1 x2) = max x1 x2
λ:r = negate <$> Range 1 2
λ:lower r
-2
λ:higher r
-1

根據您的用例,這兩種方法中的任何一種都可能更可取。

主站蜘蛛池模板: 日韩一区二区视频| 国内精品视频一区二区三区 | 国产乱码一区二区三区四| 午夜影视日本亚洲欧洲精品一区| 精品福利视频一区二区三区 | 精品视频一区二区三区免费| 老熟妇仑乱一区二区视頻| 国产日韩精品视频一区二区三区 | 亚洲伦理一区二区| 久久精品一区二区三区四区| 无码一区二区波多野结衣播放搜索 | 青娱乐国产官网极品一区| 精品视频一区二区三区四区五区| 丰满少妇内射一区| 国产精品视频一区| 99久久国产精品免费一区二区| 蜜桃AV抽搐高潮一区二区| 成人免费一区二区三区| 亚洲AV无码一区二区三区鸳鸯影院| 日本高清成本人视频一区| 亚洲中文字幕久久久一区| 中文字幕一区二区在线播放| 亚洲AV无码一区二三区| 一区二区三区四区在线视频| 亚洲AV无码一区二区三区国产| 亚洲人成网站18禁止一区 | 无码一区二区三区亚洲人妻| 精品国产一区二区三区| 精品国产日韩亚洲一区在线 | 精品欧洲av无码一区二区| 国产av一区二区三区日韩| 亚洲爆乳无码一区二区三区| 亚洲线精品一区二区三区影音先锋 | 加勒比无码一区二区三区| 男人的天堂av亚洲一区2区| 在线免费视频一区| 亚洲成人一区二区| 日本不卡一区二区三区| 麻豆aⅴ精品无码一区二区| 精品黑人一区二区三区| 精品一区狼人国产在线|