跨类型构造函数编写泛型仿函数实例? [英] Writing a generic functor instance across type constructors?
问题描述
我正在学习基本类型类,并为我的类型Test a
写了自己的functor
实现(与Maybe
一样):
I'm learning basic type classes and have written my own implementation of functor
for my type Test a
(behaves just like Maybe
):
data Test a = Test a | Emp
class FC c a where
t :: (a -> b) -> c a -> c b
instance FC Test a where
t f (Test a) = Test (f a)
t f (Emp) = Emp
instance FC Maybe a where
t f (Just a) = Just (f a)
t f (Nothing) = Nothing
是否可以实现类似的内容:
Is it possible to implement something like:
instance FC c where
t f (c v) = c (f v)
错误:
Parse error in pattern: c
换句话说,将类型构造函数抽象出来,替换为c
和v
,从而创建一个通用实例,该实例可以应用于具有上下文的任何值吗?
In other words, abstract away the type constructor, replace with c
and v
, therefore creating a general instance that can be applied to any value with a context?
推荐答案
如您所知,c a
并不是语法上有效的模式.但是,请阅读您的问题作为功能建议:这将如何工作?并非每个Functor
都有一个单元素构造函数,可以根据您的模式进行映射.一些例子:
As you've learned, c a
is not a syntactically valid pattern. But reading your question instead as a feature proposal: How would that work? Not every Functor
has a single-element constructor which can be mapped over according to your pattern. Some examples:
data Pair a = Pair a a -- more than one element
instance Functor Pair where
fmap f (Pair x y) = Pair (f x) (f y)
data Proxy a = Proxy -- no elements
instance Functor Proxy where
fmap f Proxy = Proxy
newtype Cont r a = Cont { runCont :: (a -> r) -> r } -- element appears in a double-negative position
instance Functor (Cont r) where
fmap f (Cont g) = Cont (g . (. f))
无论如何,我认为通用实例"的想法真的没有道理.该实例是您放置特定于类型的代码的地方. (它必须去某个地方!)
In any case, I don't think the idea of a "generic instance" really makes sense. The instance is where you put your type-specific code. (It has to go somewhere!)
如果您想花更少的精力编写Functor
实例,则可以使用GHC的DeriveFunctor
扩展名.
If you want to exert less effort in writing Functor
instances you can use GHC's DeriveFunctor
extension.
{-# LANGUAGE DeriveFunctor #-}
data Pair a = Pair a a deriving Functor
data Proxy a = Proxy deriving Functor
newtype Cont r a = Cont { runCont :: (a -> r) -> r } deriving Functor
这篇关于跨类型构造函数编写泛型仿函数实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!