避免在Hughes的列表仿函数实例中使用unsafeCoerce

时间:2015-07-11 21:54:55

标签: haskell typeclass functor coercion difference-lists

我有一个新类型来代表Hughes的列表(即列表构造):

newtype Hughes a = Hughes {unHughes :: [a] -> [a]}

有一些功能可以解决它:

mkHughes :: [a] -> Hughes a
mkHughes = Hughes . (++)

runHughes :: Hughes a -> [a]
runHughes h = unHughes h []

Monoid实例就像上面的函数一样简单:

instance Monoid (Hughes a) where
    mempty = Hughes id
    mappend (Hughes f) (Hughes g) = Hughes (f . g)

...但是当我到达FunctorApplicative个实例时出现问题。这是我到目前为止所提出的:

instance Functor Hughes where
    fmap f (Hughes h) = Hughes $ unsafeCoerce $ fmap f . h

instance Applicative Hughes where
    pure = Hughes . (:)
    (<*>) (Hughes f) (Hughes v) = Hughes $ unsafeCoerce $
                                  (<*>) <$> f <*> unsafeCoerce v

我遇到的问题是我不喜欢使用unsafeCoerce。有没有办法设计Functor实例而不使用它,或者它是不可避免的?

此外,我如何为此数据类型实现Monad实例?

编辑:与DList包不同,我希望保持性能提升,即不评估[a] -> [a],而是映射它。

1 个答案:

答案 0 :(得分:7)

无法实施def configure_sign_up_params devise_parameter_sanitizer.permit(:sign_up, keys: [:first_name, :last_name, :age, :height, :weight, :gender]) end 个实例。

让我们来看看Functor Hughes

的定义
Hughes

我们可以看到参数data Hughes a = Hughes ([a] -> [a]) ^ 在标记的位置显示逆变。只有当最后一个类型参数的所有外观都是协变的时,a实例才会存在。

基本上,您被要求定义一个函数Functor。问题是您无法对fmap :: (a -> b) -> ([a] -> [a]) -> [b] -> [b]执行任何操作,因此没有接受[b][b]的功能。你可以忽略它,但是仿函数法b将不会成立。

对于DList,fmap id = id实例是有效的,因为实现不导出实际的数据构造函数,只导出智能构造函数。因此,您无法构造作为任意列表处理函数的dlist值。使用提供的智能构造函数,您只能构造与Functor同构的dlists,这就是函数法所适用的原因。

如果你以某种方式将构造函数破解(带入)范围,你会发现仿函数法实际上并不适用于任意函数,例如[a]如果fmap id x /= x是某种东西比如x