使函数成为函子的实例

问题描述 投票:0回答:1

我正在尝试为具有函数属性的记录对象实现

functor
,如下所示:

data Function a =
    Function {
        , funcApply :: FData -> [Exp a] -> Either (RawException a) (Exp a)
    }

因此,

funcApply
属性需要 fmap 到类型
FData -> [Exp b] -> Either (RawException b) (Exp b)

映射返回值似乎很简单,并且让我得到类型

FData -> [Exp a] -> Either (RawException b) (Exp b)

instance Functor Function where
    fmap f (Function funcApply) =
        let funcApply' = \fData exps ->
                            case funcApply fData exps of
                                Left x -> Left $ fmap f x
                                Right x -> Right $ fmap f x
        in Function funcApply'

但我真的不知道如何映射函数参数。从逻辑上讲,感觉

funcApply
根本不需要更改,因为它已经是多态的,但编译器似乎不同意。

感谢您的帮助!

haskell typeclass functor
1个回答
0
投票

应该根据所需的实例构建类型þ您找出什么映射对您的目的有用,并构建您的类型以反映它。正如已经指出的那样,在以混合极性出现的论证中不可能是函数式的:

{-# Language DeriveFunctor            #-}
{-# Language DerivingStrategies       #-}
{-# Language StandaloneKindSignatures #-}

import Data.Kind

-- • Can't make a derived instance of
--     ‘Functor Endo’ with the stock strategy:
--     Constructor ‘Endo’ must not use the type variable in a function argument
type    Endo :: Type -> Type
newtype Endo a = Endo (a -> a)
  deriving stock Functor

一个常见的技巧是按极性拆分论证:

--                  (<–)    (->)    (->)
--                  |       |       |
type    Function :: Type -> Type -> Type
newtype Function іn out = Function (FData -> [Exp іn] -> Either (RawException out) (Exp out))

instance Profunctor Function where
  --           Contravariant   Covariant
  --           vv              vv
  dimap :: (іn <– іn') -> (out -> out') -> (Function іn out -> Function іn' out')
  dimap pre post (Function fn) = Function \fdata inExps ->
    bimap (fmap post) (fmap post) (fn fdata (map (fmap pre) inExps))

然后您还可以获得有效的

Functor (Function іn)

instance Functor (Function іn) where
  fmap :: (out -> out') -> (Function іn out -> Function іn out')
  fmap = rmap

您的评论中的解决方案使其具有多态性也有效。这意味着没有要映射的参数,因此它不能有像 Functor 或 Profunctor 这样的更高种类的实例。

type    Function :: Type
newtype Function = Function
  (forall a. FData -> [Exp a] -> Either (RawException a) (Exp a))

由于它是多态的,因此您可以自由选择如何实例化它,但它也对什么可以被视为函数施加了严格的限制。现在它必须是参数化的

a

© www.soinside.com 2019 - 2024. All rights reserved.