Functor fmap,模式匹配函数值,haskell
Functor fmap, pattern match function values, haskell
我有以下类型,想把它变成一个函子:
newtype SubsM a = SubsM {runSubsM :: Context -> Either Error (a, Env)}
到目前为止我得到了这个
instance Functor SubsM where
fmap f (SubsM a) = SubsM (\s->(Right((f a),(fst s))))
我得到一个错误,因为 a 不是预期的类型,我的问题是如何在左侧进行模式匹配?
您可以在 Either Error (a, Env)
上使用 case
进行模式匹配:
instance Functor SubsM where
fmap f (SubsM cf) = SubsM $ \c -> case (cf c) of
Left err -> Left err
Right (v, env) -> Right (f v, env)
在 Left
的情况下传播错误,在 Right
的情况下解压结果对并将 f
应用于第一个元素。
请注意,您还可以使用 ->
和 Either
的现有 Functor
实例来为您完成大部分工作:
instance Functor SubsM where
fmap g (SubsM cf) = SubsM (fmap (fmap (leftfmap g)) cf)
where
leftfmap f (a, b) = (f a, b)
(,)
的 Functor
实例映射到右边的值,而不是左边的值,所以你不能在那里使用 fmap
。如果您从 Control.Arrow
.
导入该函数,您也可以将 leftfmap
写为 first
我宁愿不用思考,当机器完全有能力为你思考时。
{-# LANGUAGE DeriveFunctor #-}
newtype SubsM a = SubsM {runSubsM :: Context -> Either Error (a, Env)}
deriving Functor
很多必要的工作已经为您完成,因为 Either a b
和 (,)
都是 Bifunctor
class.
的实例
-- Using the tuple instance
first f (x, y) == (f x, y)
-- Using the Either instance
second g (Left err) = Left err -- basically, id
first g (Right v) = Right (g v)
使用这些函数,您可以大大缩短这个时间(从 Lee 的回答开始逐步减少):
import Data.Bifunctor
instance Functor SubsM where
fmap f = SubsM . second (first f) . runSubsM
真的有人会写这样的代码,更不用说从头开始写了?可能不会。它是如何工作的并不是很明显,但是可以推导出一个
一步一步非常简单,您可能会发现中间步骤之一很有用。
我可能会这样写
instance Functor SubsM where
fmap f (SubsM cf) = SubsM $ \c -> (second . first) f (cf c)
将更深奥的部分限制为单一功能(second . first)
。
缩写形式的推导
首先,使用(,)
的Bifunctor
实例来避免模式匹配
在元组上。
-- first f (v, env) == (f v, env)
instance Functor SubsM where
fmap f (SubsM cf) = SubsM $ \c -> case (cf c) of
Left err -> Left err
Right t -> Right (first f t)
接下来,使用 Either a b
的 Bifunctor
实例来避免对 cf c
的 return 值进行模式匹配:
-- second (first f) (Left err) == Left Err
-- second (first f) (Right t) == Right (first f) t
instance Functor SubsM where
fmap f (SubsM cf) = SubsM $ \c -> second (first f) (cf c)
您还可以通过解包来避免对 SubsM
值进行模式匹配
它在右侧 runSubsM
:
instance Functor SubsM where
fmap f cf = SubsM $ \c -> second (first f) ((runSubsM cf) c)
最后,我们开始应用函数组合来消除显式
尽可能提出论点。
instance Functor SubsM where
-- fmap f cf = SubsM $ \c -> second (first f) ((runSubsM cf) c)
-- fmap f cf = SubsM $ \c -> second (first f) . (runSubsM cf) $ c
-- fmap f cf = SubsM $ second (first f) . (runSubsM cf)
-- One more function composition allows us to drop cf as an
-- explicit argument
fmap f = SubsM . second (first f) . runSubsM
我有以下类型,想把它变成一个函子:
newtype SubsM a = SubsM {runSubsM :: Context -> Either Error (a, Env)}
到目前为止我得到了这个
instance Functor SubsM where
fmap f (SubsM a) = SubsM (\s->(Right((f a),(fst s))))
我得到一个错误,因为 a 不是预期的类型,我的问题是如何在左侧进行模式匹配?
您可以在 Either Error (a, Env)
上使用 case
进行模式匹配:
instance Functor SubsM where
fmap f (SubsM cf) = SubsM $ \c -> case (cf c) of
Left err -> Left err
Right (v, env) -> Right (f v, env)
在 Left
的情况下传播错误,在 Right
的情况下解压结果对并将 f
应用于第一个元素。
请注意,您还可以使用 ->
和 Either
的现有 Functor
实例来为您完成大部分工作:
instance Functor SubsM where
fmap g (SubsM cf) = SubsM (fmap (fmap (leftfmap g)) cf)
where
leftfmap f (a, b) = (f a, b)
(,)
的 Functor
实例映射到右边的值,而不是左边的值,所以你不能在那里使用 fmap
。如果您从 Control.Arrow
.
leftfmap
写为 first
我宁愿不用思考,当机器完全有能力为你思考时。
{-# LANGUAGE DeriveFunctor #-}
newtype SubsM a = SubsM {runSubsM :: Context -> Either Error (a, Env)}
deriving Functor
很多必要的工作已经为您完成,因为 Either a b
和 (,)
都是 Bifunctor
class.
-- Using the tuple instance
first f (x, y) == (f x, y)
-- Using the Either instance
second g (Left err) = Left err -- basically, id
first g (Right v) = Right (g v)
使用这些函数,您可以大大缩短这个时间(从 Lee 的回答开始逐步减少):
import Data.Bifunctor
instance Functor SubsM where
fmap f = SubsM . second (first f) . runSubsM
真的有人会写这样的代码,更不用说从头开始写了?可能不会。它是如何工作的并不是很明显,但是可以推导出一个 一步一步非常简单,您可能会发现中间步骤之一很有用。
我可能会这样写
instance Functor SubsM where
fmap f (SubsM cf) = SubsM $ \c -> (second . first) f (cf c)
将更深奥的部分限制为单一功能(second . first)
。
缩写形式的推导
首先,使用(,)
的Bifunctor
实例来避免模式匹配
在元组上。
-- first f (v, env) == (f v, env)
instance Functor SubsM where
fmap f (SubsM cf) = SubsM $ \c -> case (cf c) of
Left err -> Left err
Right t -> Right (first f t)
接下来,使用 Either a b
的 Bifunctor
实例来避免对 cf c
的 return 值进行模式匹配:
-- second (first f) (Left err) == Left Err
-- second (first f) (Right t) == Right (first f) t
instance Functor SubsM where
fmap f (SubsM cf) = SubsM $ \c -> second (first f) (cf c)
您还可以通过解包来避免对 SubsM
值进行模式匹配
它在右侧 runSubsM
:
instance Functor SubsM where
fmap f cf = SubsM $ \c -> second (first f) ((runSubsM cf) c)
最后,我们开始应用函数组合来消除显式 尽可能提出论点。
instance Functor SubsM where
-- fmap f cf = SubsM $ \c -> second (first f) ((runSubsM cf) c)
-- fmap f cf = SubsM $ \c -> second (first f) . (runSubsM cf) $ c
-- fmap f cf = SubsM $ second (first f) . (runSubsM cf)
-- One more function composition allows us to drop cf as an
-- explicit argument
fmap f = SubsM . second (first f) . runSubsM