具体来说,受 J 的共轭运算符 (g&.f = (f inverse)(g)(f)) 的启发,我需要一种方法来增加具有附加信息的函数。显而易见的方法是使用 ADT。就像是:
data Isomorphism a b = ISO {FW (a -> b) , BW (b -> a)}
(FW f) `isoApp` x = f x
(BW g) `isoApp` x = g x
但是当大多数时候你只需要 forward 函数时,对应用程序函数的需求确实会损害代码的可读性。非常有用的是一个类:
class Applyable a b c | a b -> c where
apply :: a -> b -> c
(我认为 b 可以用存在量词隐含,但我不能确定我不会弄错签名)
现在应用程序将被隐式化,因此您可以只写
f x
就像任何其他功能一样。前任:
instance Applyable (a -> b) a b where
apply f x = f x
instance Applyable (Isomorphism a b) a b where
apply f x = (FW f) x
inverse (Iso f g) = Iso g f
那么你可以写这样的东西:
conjugate :: (Applyable g b b) => g -> Iso a b -> b -> a
f `conjugate` g = (inverse f) . g . f
理想情况下,可以推断出类型签名
但是,这些语义似乎很复杂,因为您还需要修改 (.) 以支持 Applyable 而不是函数。有没有办法简单地欺骗类型系统将可应用数据类型视为所有正常目的的函数?是否有根本原因表明这是不可能的/一个坏主意?