平方矩阵的函子

时间:2019-09-14 13:20:13

标签: haskell types nested functor

在我上一个问题(Nested datatype for square matrices)中,引入了数据类型Square。现在,我想为其编写一个仿函数实例。因此,我首先从所有四种类型的地图函数开始。我已经为NilCons做到了这一点:

mapNil :: ((a -> b) -> a -> b) -> (Nil (a -> b) -> Nil a -> Nil b )
mapNil map f Nil = Nil


mapCons :: (forall b . ((a -> b) -> a -> b) -> (t (a -> b) -> t a -> t b))
        -> ((a -> b) -> a -> b)
        -> ((Cons t (a -> b)) -> Cons t a -> Cons t b)
mapCons mapT mapA (Cons f consf) (Cons x consx) =  Cons (mapA f x) (mapT mapA consf consx)

现在,Square'类型:

mapSquare' :: (forall b . ((a -> b) -> a -> b) -> (t (a -> b) -> t a -> t b))
           -> ((a -> b) -> a -> b)
           -> ((Square' t (a -> b)) -> Square' t a -> Square' t b)
mapSquare' mapT mapA (Zero fs) (Zero xs) = Zero (mapT (mapT mapA) fs xs) -- it is wrong
mapSquare' mapT mapA (Succ fs) (Succ xs) = mapSquare' (mapCons mapT) mapA fs xs

然后我将执行以下操作:

mapSquare = ...

-- this is, actually, the final goal:
instance Functor Square where
fmap = mapSquare

到目前为止,对于我的mapSquare' Haskell来说:

• Occurs check: cannot construct the infinite type: a ~ t a
  Expected type: (a -> t b) -> a -> t b
    Actual type: t (a -> b) -> t a -> t b
• In the first argument of ‘mapT’, namely ‘(mapT mapA)’
  In the first argument of ‘Zero’, namely ‘(mapT (mapT mapA) fs xs)’
  In the expression: Zero (mapT (mapT mapA) fs xs)

我的计划是,(mapT mapA)将在(t (t a))(t a)级别之间“提升”它们。我怎么了多谢您的协助。

2 个答案:

答案 0 :(得分:4)

您不能使用mapSquare,因为该类型限制太多。函子的类型为fmap :: Functor f => (c -> d) -> f c -> f d。但是((a -> b) -> a -> b) -> (Square (a -> b)) -> Square a -> Square b仅覆盖其中的一部分。您的mapSquare'看起来更像是“ 顺序应用程序(<*>) :: Applicative f => f (a -> b) -> f a -> f b。请注意,(<*>)需要两个f x项,而不是fmap那样的项。

如果您要声明Square的一个实例,则FunctorNil可能是一个ConstFunctor的实例,具体取决于实现它的方式。 Functor的实例。我们可以轻松地使它们成为instance Functor Nil where fmap _ Nil = Nil instance Functor t => Functor (Cons t) where fmap f (Cons x xs) = Cons (f x) (fmap f xs)的实例:

Square'

现在,我们可以使Functor成为instance Functor t => Functor (Square' t) where fmap f (Zero x) = Zero (fmap (fmap f) x) fmap f (Succ x) = Succ (fmap f x)的实例,

{-# LANGUAGE DeriveFunctor #-}

data Square' t a = Zero (t (t a) ) | Succ (Square' (Cons t) a) deriving Functor
data Nil a = Nil deriving Functor
data Cons t a = Cons a (t a) deriving Functor

您实际上并不自己生成那些。您可以使用DeriveFunctor [ghc-doc]编译器选项,并让编译器为您派生功能:

#config
--- 
lists:
  - filename: filename.xlsx
    template: filename_template.xlsx
    type: classType #this value is ommitted
    ...

这将构造此处讨论的指定函子。

答案 1 :(得分:1)

这是我要提出的问题的答案,而不是实际提出的问题,因为我的说法有点含糊。 首先,我确实搞砸了,将(<*>)fmap混在一起,感谢@WillemVanOnsem指出了这一点。 所以,我真正想做的是:

mapNil :: ((a -> b) -> a -> b) -> ((a -> b) -> Nil a -> Nil b )
mapNil mapA f Nil = Nil

mapCons :: (forall b . ((a -> b) -> a -> b) -> ((a -> b) -> t a -> t b))
        -> ((a -> b) -> a -> b)
        -> ((a -> b) -> Cons t a -> Cons t b)
mapCons mapT mapA f (Cons x consx) =  Cons (f x) (mapT mapA f consx)

然后...

mapSquare' :: (forall b . ((a -> b) -> a -> b) -> ((a -> b) -> t a -> t b))
           -> ((a -> b) -> a -> b)
           -> ((a -> b) -> Square' t a -> Square' t b)
mapSquare' mapT mapA f (Zero xs) = Zero (mapT (mapT mapA) f xs) 
mapSquare' mapT mapA f (Succ xs) = Succ (mapSquare' (mapCons mapT) mapA f xs)

t是类型* -> *的类型构造函数,因此tmapT)上的映射函数应在其参数({{1} })作为参数。所以我需要mapAmapT