gpt4 book ai didi

haskell - 存储和检索某个类型类的对象 - 可能吗?如果是,如何?

转载 作者:行者123 更新时间:2023-12-01 09:18:44 25 4
gpt4 key购买 nike

假设我有一些类型类 Foo 和一些数据类型 FooInstFoo 的实例:

class Foo a where
foo :: a -> String

data FooInst = FooInst String

instance Foo FooInst where
foo (FooInst s) = s

现在,我想定义一个数据类型来存储一个对象,该对象的类型在 Foo 类型类中,并且能够从该数据类型中提取该对象并使用它。

我发现的唯一方法是使用 GADTs 和 Rank2Types 语言扩展并像这样定义数据类型:

data Container where
Container :: { content :: Foo a => a } -> Container

但是,问题是,我不能使用 content 选择器从容器中获取内容:

cont :: Container
cont = Container{content = FooInst "foo"}

main :: IO ()
main = do
let fi = content cont
putStrLn $ foo fi

导致编译错误

Cannot use record selector ‘content’ as a function due to escaped type variables
Probable fix: use pattern-matching syntax instead

但是当我将 let ... 行修改为

let Conainer fi = cont

我遇到了一个相当有趣的错误

My brain just exploded
I can't handle pattern bindings for existential or GADT data constructors.
Instead, use a case-expression, or do-notation, to unpack the constructor.

如果我再次尝试修改 let ... 行以使用 case-expression

let fi = case cont of
Container x -> x

我得到一个不同的错误

Couldn't match expected type ‘t’ with actual type ‘a’
because type variable ‘a’ would escape its scope
This (rigid, skolem) type variable is bound by
a pattern with constructor
Container :: forall a. (Foo a => a) -> Container,
in a case alternative
at test.hs:23:14-24

那么,我怎样才能存储一个类型分类的东西并取回它呢?

最佳答案

与:

data Container where
Container :: {content :: Foo a => a} -> Container

类型类约束甚至没有强制执行。那就是

void :: Container
void = Container {content = 42 :: Int}

类型检查,即使 42::Int 不是 Foo 的实例。

但如果你改为:

data Container where
Container :: Foo a => {content :: a} -> Container
  1. 您不再需要 Rank2Types 语言扩展。
  2. 强制执行类型类约束;因此上面的 void 示例将不再进行类型检查。
  3. 此外,您可以通过模式匹配在内容上调用 foo(或任何其他带有签名 Foo a => a -> ... 的函数) :

    case cont of Container {content = a} -> foo a

关于haskell - 存储和检索某个类型类的对象 - 可能吗?如果是,如何?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38171870/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com