Haskell 类型类可以部分实现吗?

Can Haskell Typeclasses be Partially Implemented?

我想做一个对类型来表示模运算。我做了它的构造函数

{- LANGUAGE GADTs -}
data Zn e where
    Zn :: Integer -> Integer -> Zn Integer

因为我希望能够 fmap 处理它和所有事情。 因此,如果我尝试将其设为 Functor 实例

instance Functor Zn where
    fmap f (Zn s n) = Zn s $ mod (f n) s

我得到 Could not deduce: b ~ Integer from the context: a ~ Integer。当然它不能推断出这一点,因为这种数据类型对所有 ab 没有有意义的 fmap :: (a -> b) -> Zn a -> Zn b 概念,但只要 ab ] 是这样的,实际上可以从它们构造 Zn 个实例(即 Integer)。我还尝试使用 Zn 构造函数,所有方法都需要 Integral e 但我遇到了类似的问题。在这种情况下,s 的类型为 a,因此用它构造 Znf n :: b 失败。在第二种情况下,我可以将 sa 转换为 Integer,然后再转换为 b,但这很笨拙。整个事情有点笨拙。我这样做是因为我希望能够在映射函数后实现 FunctorApplicative 来执行 mod 这样我就可以将 + 实现为 liftA2 (+) 等等。模数 s 应该是类型的一部分,但据我所知,依赖类型在 Haskell 中不实用。

是否可以让种类为 * -> * 的类型仅对某些参数实现 Functor

您正在寻找 MonoFunctor。它就像 Functor,但使用固定的内部类型而不是参数多态。以下是您如何为您的类型实施它:

{-# LANGUAGE TypeFamilies #-}

import Data.MonoTraversable

data Zn = Zn Integer Integer

type instance Element Zn = Integer

instance MonoFunctor Zn where
    omap f (Zn s n) = Zn s $ mod (f n) s

但是,请注意,这种情况并不完全合法。你最好只做一个 modMap 函数或其他东西,以避免人们对它的工作方式做出错误的假设。