[英]Defining a functor instance for this datatype
我正在尝试为数据类型Terms
定义一个仿函数实例,如下所示:
data Terms a = Var a | App (Terms a) (Terms a) | Abs (Terms (Maybe a))
| Const Integer | Add (Terms a) (Terms a)
| IfZero (Terms a) (Terms a) (Terms a) | Y
deriving (Show,Eq)
但是,我在处理Abs
的案例时遇到了麻烦。
我的定义目前如下所示:
instance Functor Terms where
fmap f (Var x) = Var (f x)
fmap f (App t1 t2) = App (fmap f t1) (fmap f t2)
fmap f (Abs t) = Abs (fmap f t)
fmap f (Const n) = Const n
fmap f (Add t1 t2) = Add (fmap f t1) (fmap f t2)
fmap f (IfZero t1 t2 t3) = IfZero (fmap f t1) (fmap f t2) (fmap f t3)
fmap f Y = Y
为了将 function 应用于该术语,我尝试了几种不同的方法来绕过Maybe
,但有些东西我不太明白。 我知道Maybe
类型本身就是一个仿函数,这意味着fmap
应该自动处理它,我只是不确定如何解决它不能作为Maybe
返回的事实。
是的Maybe
本身就是一个仿函数,因此它有自己的fmap
:
fmap f (Abs t) = Abs (fmap₁ (fmap₂ f) t)
-- t :: Terms (Maybe a)
-- f :: a -> b
-- fmap₂ f :: Maybe a -> Maybe b
-- fmap₁ (fmap₂ f) :: Terms (Maybe a) -> Terms (Maybe b)
下标索引不是代码的一部分,仅用于说明目的。 或者我们可以使用TypeApplications
来区分它们:
*Main> :set -XTypeApplications
*Main> fmap @Maybe (+1) $ Just 7
Just 8
*Main> fmap @Terms (+1) $ Abs $ Var $ Just 8
Abs (Var (Just 9))
但这里不需要它们,普通的fmap
也可以工作—— Haskell 知道应用哪个,根据参数的类型:
*Main> fmap (+1) $ Just 7
Just 8
*Main> fmap (+1) $ Abs $ Var $ Just 8
Abs (Var (Just 9))
错误来自这一行:
fmap f (Abs t) = Abs (fmap f t)
Abs
包含一个Maybe (Term a)
,而您想得到一个Maybe (Term b)
,但f
的类型a -> b
。 因此,当您尝试对其进行fmap
时,您将a
Term a
传递给一个接收 . 显然这行不通。 相反,使用fmap f
创建一个Term a -> Term b
,然后fmap
(创建一个双fmap
):
fmap f (Abs t) = Abs (fmap (fmap f) t)
或者使用fmap. fmap
fmap. fmap
您可以将Term (Maybe a)
定义为仿函数(= Scoped Maybe a
)。
{-# Language DerivingVia #-}
type Scoped :: (Type -> Type) -> (Type -> Type)
newtype Scoped exp a = Scoped (exp (Maybe a))
deriving (Functor, Applicative, Alternative, Foldable, Arbitrary1, ..)
via Compose exp Maybe
这是 Edward Kmett 的绑定库所采用的方法。
type Scope :: Type -> (Type -> Type) -> (Type -> Type)
newtype Scope b exp a = Scope (exp (Var b (exp a)))
type Scope :: Type -> (Type -> Type) -> (Type -> Type)
newtype Scope b exp a = Scope (exp (Var b a))
其中Var
= Either
:
type Var :: Type -> Type -> Type
data Var b a
= B b -- ^ this is a bound variable
| F a -- ^ this is a free variable
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.