我可以表达子类化约束吗?

n. *_* m. 6 haskell types existential-type typeclass

仍然在约束上玩存在主义(只是探索这个设计空间,我知道许多 Haskellers 认为它​​很糟糕)。有关更多信息,请参阅此问题

{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE ConstraintKinds #-}
{-# Language TypeApplications #-}

import GHC.Exts (Constraint)

class Foo a where
   foo :: a -> Int

class Foo a => Bar a where
   bar :: a -> String

instance Foo Int where
   foo = id

instance Bar Int where
   bar = show

data Obj cls = forall o. (cls o) => Obj o

fooable = Obj @Foo $ (42 :: Int)
barable = Obj @Bar $ (42 :: Int)

doFoo :: Obj Foo -> Int
doFoo (Obj x) = foo x
Run Code Online (Sandbox Code Playgroud)

现在我有这个问题。doFoo fooable有效,但doFoo barable无效。

• Couldn't match type ‘Bar’ with ‘Foo’
  Expected type: Obj Foo
    Actual type: Obj Bar
• In the first argument of ‘doFoo’, namely ‘barable’
  In the expression: doFoo barable
  In an equation for ‘it’: it = doFoo barable
Run Code Online (Sandbox Code Playgroud)

这当然是真的。Obj Foo是不同的Obj Bar

我可以给一个合适的类型doFoo吗?基本上我想要一个类型,Obj cls where cls is a subclass of Foo但我找不到表达它的方法。请耐心等待,我对这些狂野的奇妙类型不熟悉。

chi*_*chi 6

您可以为此使用量化约束:

{-# LANGUAGE QuantifiedConstraints #-}

doFoo :: forall c . (forall a. c a => Foo a) => Obj c -> Int
doFoo (Obj x) = foo x
Run Code Online (Sandbox Code Playgroud)

本质上,doFoo采用 any Obj c,其中c是隐含的任何类型类Foo,即满足量化约束的类型类

forall a. c a => Foo a
Run Code Online (Sandbox Code Playgroud)