约束实例方法

Mic*_*Fox 3 haskell

我想写:

{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE DatatypeContexts #-}

data Ord a => S a = ...
toList :: Ord a => S a -> [a]
fromList :: Ord a => [a] -> S a

instance Functor S where
  fmap :: (Ord a, Ord b) => (a -> b) -> S a -> S b
  fmap f = fromList . fmap f . toList
Run Code Online (Sandbox Code Playgroud)

但GHC一直在打击我

方法签名与类不匹配

问题:

  • 你知道一个解决方法吗?
  • 这个限制解决了什么问题?

bhe*_*ilr 5

你不能,简单地说.在Functor类的定义,使得它必须与所有的工作a -> b,而不仅仅是一些a -> b.不过,你可以定义自己的FunctorOrd.

class FunctorOrd f where
    fmapOrd :: (Ord a, Ord b) => (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)

但是,这可能不是你想要的.我猜你想要构建某种类似集合的结构,在内部使用二叉树来保持唯一性.如果我做某事,会发生什么

s :: S Int
s = fromList [1..100]

t :: S Bool
t = fmap even s
Run Code Online (Sandbox Code Playgroud)

这将简单地应用于集合中的even每一个Int,它根本不能改变结构,只是它包含的内容.你最好写一个像这样的函数

smap :: (Ord a, Ord b) => (a -> b) -> S a -> S b
smap f = fromList . map f . toList
Run Code Online (Sandbox Code Playgroud)

或者可能更有效,但仍然能够改变结构本身,而不仅仅是价值.

这不是一个完全限制,而是Functor必须满足法律才能fmap使行为正常.这可能看起来不是什么大问题,但是请查看各种ListT实施的有争议的历史以及它们如何不满足monad法则.