用于编写(a-> a)函数的Functor/Applicative-like类型类而不是(a-> b)?

mis*_*bee 4 haskell

我有一个看起来像这样的类型:

newtype Canonical Int = Canonical Int
Run Code Online (Sandbox Code Playgroud)

和一个功能

canonicalize :: Int  -> Canonical  Int
canonicalize =  Canonical . (`mod` 10)  -- or whatever
Run Code Online (Sandbox Code Playgroud)

(Canonical类型可能并不重要,它只是用于区分"原始"值和"规范化"值.)

我想创建一些机器,以便我可以规范化函数应用程序的结果.

例如:( 编辑:固定的虚假定义)

cmap :: (b->Int) -> (Canonical b) -> (Canonical Int)
cmap f (Canonical x) = canonicalize $ f x

cmap2 :: (b->c->Int) -> (Canonical b) -> (Canonical c) -> (Canonical Int)
cmap2 f (Canonical x) (Canonical y) = canonicalize $ f x y
Run Code Online (Sandbox Code Playgroud)

这表面上与Functor和Applicative类似,但它并不完全,因为它太专业了:我实际上不能编写函数(按照Functor/Applicative的同态定律的要求),除非'b'是Int.

我的目标是利用现有的,而不是写我自己的变种一样的库函数/组合程序,cmap,cmap2.那可能吗?是否有不同的类型类或构造Canonical类型的不同方式来实现我的目标?

我尝试过其他结构,比如

newtype Canonical a = Canonical { value :: a, canonicalizer :: a -> a }
Run Code Online (Sandbox Code Playgroud)

但是这会遇到同样的非可组合性问题,因为我无法将一个规范化器转换为另一个规范化器(我只想使用结果类型的规范化器,它总是Int(或Integral a)

我不能像这样强制"仅限专业化",这不是有效的Haskell:

instance (Functor Int) (Canonical Int) 
Run Code Online (Sandbox Code Playgroud)

(和类似的变化)

我也试过了

newtype (Integral a) => Canonical a = Canonical a -- -XDatatypeContexts
instance (Integral a) => Functor Canonical where
  fmap f (Canonical x) = canonicalize  $ f x
Run Code Online (Sandbox Code Playgroud)

但GHC表示这DatatypeContexts已被弃用,这是一个坏主意,更严重的是,我得到:

 `Could not deduce (Integral a1) arising from a use of 'C'   
 from the context (Integral a)
 bound by the instance declaration
 [...] fmap :: (a1 -> b) -> (C a1 -> C b)
Run Code Online (Sandbox Code Playgroud)

我认为这是说,约束Integral a实际上不能用于约束fmap(Integral -> Integral)我希望的方式,这是有点明显的(因为fmap有两个类型变量):-(

当然,这也不是有效的Haskell

instance (Integer a) => Functor Canonical where
Run Code Online (Sandbox Code Playgroud)

是否有类似的类型类我可以使用,或者我是否错误地试图使用类型类的"隐式规范化函数调用的结果"的功能?

Mic*_*man 5

我认为你想要实现的是单可遍历的软件包,在本例中是MonoFunctor类型类.

  • 它在不稳定的包装套件中可用.在我们创建9月稳定快照的时候,单遍历不够稳定. (2认同)