如何为容纳函数的新类型构造fmap

mBr*_*024 4 haskell functor newtype

假设我要定义一个包含函数的新类型:

newtype Test m a = Test(m -> (a, m))
Run Code Online (Sandbox Code Playgroud)

这可以用来容纳某种状态。

现在让我们说我想为这个新类型实现fmap。

instance Functor (Test m) where
    --fmap :: (a -> b) -> Test m a -> Test m a -> b
    fmap f (Test f1) (Test f2) = ?
Run Code Online (Sandbox Code Playgroud)

由于新类型房屋具有功能,因此无法使用模式匹配将f1和f2分开。

例如,我最初认为我可以将f2的输入值传递给调用f1以产生一个(a,m)元组,但是我认为您不能做到这一点。

tup = f1 (get input of f2)
Run Code Online (Sandbox Code Playgroud)

有人能为我提供处理这种情况时我所缺少的概念吗?或者这不可能吗?

谢谢

更新

非常感谢Redu和Willem Van Onsem。

似乎我对如何使用合成运算符(。)缺乏了解。

基本上,这里的关键是使用(。)来获取元组的第一个元素,然后执行一堆局部函数定义以进入fmap所需的状态。这是我的fmap实现,没有使用库函数。故意冗长以帮助理解。

alterParamStateHelper :: (a -> b) -> (m -> a) -> m -> (b, m)
alterParamStateHelper f1 f2 m = (b, m)
  where 
    a = f2 e
    b = f1 a

alterParamState :: (a -> b) -> (m -> (a, m)) -> (m -> (b, m))
alterParamState f1 f2 = alterParamStateHelper f1 h1
  where
    h1 = fst . f2--m -> a

instance Functor (Test m) where
  -- fmap :: (a -> b) -> Test m a -> Test m b
  fmap f1 (Test f2) = Test (alterParamState f1 f2)
Run Code Online (Sandbox Code Playgroud)

Wil*_*sem 6

由于新类型具有功能,因此无法使用模式匹配进行拆分f1f2分离。

您的fmap签名在这里有问题。fmap有签名fmap :: Functor f => (a -> b) -> f a -> f b,如果是f ~ Test m,那么签名是fmap :: (a -> b) -> Test m a -> Test m b

因此fmap,我们可以在此处定义一个“后处理”函数结果的位置。因此,我们构造了一个新函数,该函数将使用旧函数构造一个2元组(a, m),然后调用f第一个项目,从而构造一个元组(b, m)

import Control.Arrow(first)

instance Functor (Test m) where
    fmap f (Test g) = Test (first f . g)
Run Code Online (Sandbox Code Playgroud)