You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Haskell自定义类型MyEither实现Functor等类型类实例

问题解答

前置提醒

你自定义的MyEither里的Nothing构造子会和Prelude中Maybe类型的Nothing重名,编译会报错,有两种解决方式:

  • 要么在代码文件头部添加导入声明隐藏Prelude的Nothing:import Prelude hiding (Nothing)
  • 更稳妥的方案是给自定义构造子加前缀改为MyNothing,避免命名冲突,以下示例均采用该命名方案。

问题1:新增空分支的处理逻辑

所有Functor、Applicative、Monad实例中,新增的空分支(MyNothing)都遵循短路中断语义,和MyLeft分支的处理逻辑一致:遇到该分支时直接返回自身,不执行任何映射、函数应用或者绑定操作,完全符合这三个类型类的定律要求。

问题2:deriving语句的使用规则

deriving语句不需要写在你手动实现的类型类实例中:

  • 你现在写在data定义尾部的deriving (Eq, Show),作用是让编译器自动为MyEither类型生成Eq和Show两个类型类的实例代码,不需要你手动实现。
  • 只有当你需要让编译器自动派生某类型类的实例时才需要使用deriving,你要手动实现的Functor、Applicative、Monad实例不需要加该关键字。

完整实例实现代码

-- 自定义类型定义
data MyEither a b = MyLeft a | MyRight b | MyNothing
  deriving (Eq, Show) -- 自动派生Eq、Show实例,不需要手动实现

-- Functor实例实现
instance Functor (MyEither a) where
  fmap _ (MyLeft x) = MyLeft x
  fmap f (MyRight y) = MyRight (f y)
  fmap _ MyNothing = MyNothing

-- Applicative实例实现
instance Applicative (MyEither a) where
  pure = MyRight
  (MyLeft e) <*> _ = MyLeft e
  MyNothing <*> _ = MyNothing
  (MyRight f) <*> r = fmap f r

-- Monad实例实现
instance Monad (MyEither a) where
  (MyLeft e) >>= _ = MyLeft e
  MyNothing >>= _ = MyNothing
  (MyRight x) >>= f = f x

内容的提问来源于stack exchange,提问作者Nightysky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 08:24:05