繁体   English   中英

为此数据类型定义函子实例

[英]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 的绑定库所采用的方法。

Bound.Scope.Scope

type    Scope :: Type -> (Type -> Type) -> (Type -> Type)
newtype Scope b exp a = Scope (exp (Var b (exp a)))

Bound.Scope.Simple.Scope

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM