我是Haskell的新手,刚玩了一段时间。

我写了一个轻量级的OOP模拟:

 --OOP.hs
 {-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, UndecidableInstances, ScopedTypeVariables, FunctionalDependencies #-}

module OOP where
class Provides obj iface where
    provide::obj->iface
    (#>)::obj->(iface->a)->a
    o #> meth = meth $ provide o

class Instance cls obj | obj -> cls where
    classOf::obj->cls

class Implements cls iface where
    implement::(Instance cls obj)=>cls->obj->iface

instance (Instance cls obj, Implements cls iface)=>Provides obj iface where
    provide x = implement (classOf x::cls) x

像这样使用它:
 --main.hs
 {-# LANGUAGE MultiParamTypeClasses #-}

import OOP
data I1 = I1
getI1::I1->String
getI1 i1 = "Interface 1"

data I2 = I2
getI2::I2->String
getI2 i2 = "Interface 2"


data C = C


instance Implements C I1 where
    implement C o = I1

instance Implements C I2 where
    implement C o = I2

data O = O
instance Instance C O where
    classOf o = C

main = do
    putStrLn (O #> getI1)
    putStrLn (O #> getI2)

我读到UndecidableInstances功能非常不方便,并且可能导致编译器中出现stack overflows。所以我有两个问题。
  • 是否可以改进此代码,以保持实例和类数据类型之间以及接口(interface)和类之间的易用性和1 to N关系?
  • 可能是使用单个参数类型类实现的类似逻辑吗?
  • 最佳答案

    在这种情况下,您可以使用不确定的实例。

    instance (Instance cls obj, Implements cls iface)=>Provides obj iface where
    

    之所以无法确定,是因为您可能有一个InstanceImplements的实例,而该实例又依赖于Provides导致了循环。

    但是,在这种情况下,您根本不需要Provides类,因为您仅从其他两个类的方法上实现了它的实现!

    相反,您可以将provides#>拉出,成为具有适当InstanceImplements约束的顶级函数,并且不会丢失任何内容,并且无需使用不确定的实例。

    但是,您确实需要/想要MPTC,这很好...

    关于Haskell MultiParamTypeClasses和UndecidableInstances,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21216861/

    10-12 17:51