gpt4 book ai didi

haskell - GADT 与 MultiParamTypeClasses

转载 作者:行者123 更新时间:2023-12-03 23:48:15 26 4
gpt4 key购买 nike

我正在努力掌握GADTs ,我查看了GADTs example在 GHC 的手册中。据我所知,MultiParamTypeClasses 可以做同样的事情。 :

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies,
FlexibleInstances, UndecidableInstances #-}

class IsTerm a b | a -> b where
eval :: a -> b

data IntTerm = Lit Int
| Succ IntTerm
data BoolTerm = IsZero IntTerm
data If p a = If p a a
data Pair a b = Pair a b

instance IsTerm IntTerm Int where
eval (Lit i) = i
eval (Succ t) = 1 + eval t

instance IsTerm BoolTerm Bool where
eval (IsZero t) = eval t == 0

instance (IsTerm p Bool, IsTerm a r) => IsTerm (If p a) r where
eval (If b e1 e2) = if eval b then eval e1 else eval e2

instance (IsTerm a c, IsTerm b d) => IsTerm (Pair a b) (c, d) where
eval (Pair e1 e2) = (eval e1, eval e2)

请注意,对于 eval,我们有完全相同的构造函数和完全相同的代码。 (跨实例定义传播)如 GHC 的 GADTs例子。

那么, GADTs 到底是怎么回事? ? GADTs 有什么我可以做的吗?我不能用 MultiParamTypeClasses ?还是他们只是提供了一种更简洁的做事方式,而我可以用 MultiParamTypeClasses 来做这些事情?反而?

最佳答案

您可以方便地将相同类型但具有不同构造函数的 GADT 值放入容器中,

map eval [Lit 1, If (IsZero (Lit 3)) (Lit 4) (Succ (Lit 6))]

很简单,但至少很难使用不同的类型和具有功能依赖关系的 MPTC 来获得相同的结果。在您的多参数类型类方法中, LitIf是不同类型的构造函数,因此需要一个包装类型来将它们放入同一个容器中。据我所知,包装器类型必须是存在类型 à la
data Wrap t = forall a. (IsTerm a t) => Wrapper a

带着
instance IsTerm (Wrap t) t where
eval (Wrapper e) = eval e

确保某些类型的安全性和 map 的能力函数如 eval在列表之上。所以你已经中途或更多地回到了 GADT,减去了便利。

我不确定 GADT 是否允许您做任何没有它们您无法实现的事情,但有些事情会牺牲 很多的优雅。

关于haskell - GADT 与 MultiParamTypeClasses,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10994508/

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