【发布时间】:2014-01-13 16:35:48
【问题描述】:
我有一个看起来像这样的类型:
newtype Canonical Int = Canonical Int
还有一个函数
canonicalize :: Int -> Canonical Int
canonicalize = Canonical . (`mod` 10) -- or whatever
(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
这在表面上类似于 Functor 和 Applicative,但并不完全相似,因为它太专业了:除非“b”是 Int,否则我实际上无法组合函数(按照 Functor/Applicative 的同态法则的要求)。
我的目标是使用现有的库函数/组合器,而不是编写我自己的变体,例如 cmap、cmap2。那可能吗?是否有不同的类型类或不同的方式来构建规范类型,以实现我的目标?
我尝试过其他结构,例如
newtype Canonical a = Canonical { value :: a, canonicalizer :: a -> a }
但这遇到了同样的不可组合性问题,因为我无法将一个规范化器转换为另一个(我只想使用结果类型的规范化器,它始终为Int(或Integral a)
而且我不能像这样强制“仅专业化”,这不是有效的 Haskell:
instance (Functor Int) (Canonical Int)
(以及类似的变体)
我也试过
newtype (Integral a) => Canonical a = Canonical a -- -XDatatypeContexts
instance (Integral a) => Functor Canonical where
fmap f (Canonical x) = canonicalize $ f x
但是 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)
我认为约束Integral a 实际上不能用于将fmap 约束为(Integral -> Integral) 我希望的方式,这很明显(因为fmap 有两个类型变量): -(
当然这也不是有效的 Haskell
instance (Integer a) => Functor Canonical where
是否有类似的类型类我可以使用,或者我尝试使用类型类来实现“隐式规范化函数调用的结果”的功能是错误的?
【问题讨论】:
-
让我们退后一步。您确定类型签名
cmap2 :: (b->c->Int) -> (Canonical Int) -> (Canonical Int)描述了您想要的吗?因为它看起来很没有意义。它也与Functor无关。下面是一个有效函子签名的示例:(Int -> Int) -> Canonical Int -> Canonical Int。 -
我的错误,我在将更复杂的类型简化为在 SO 上提出的问题时犯了错误。我已经(试图)改进定义,进行了编辑。
标签: haskell