具有单个构造函数的GADT

时间:2019-07-19 18:37:01

标签: haskell types

这是示例代码:

{-# LANGUAGE GADTs #-}

data NumGadt a where
  NumGadt :: Num a => a -> Int -> String -> Bool -> NumGadt a

getNum :: NumGadt a -> a
getNum (NumGadt a _ _ _) = a

现在让我们说我要编写一个这样的函数:

successor :: NumGadt a -> a
successor x = 1 + getNum x

问题是这无法编译,并显示有关No instance for (Num a)

的错误

对此的可能解决方案是

successor :: NumGadt a -> a
successor x@(NumGadt _ _ _ _) = 1 + getNum x

但这非常丑陋,在更多地方使用它会变得非常丑陋。

问题是,有没有办法使编译器意识到这种类型只有一个构造函数,并从中推断出约束条件?

1 个答案:

答案 0 :(得分:6)

您可以定义一个"file:mydbfile.db?cache=shared&_mode=rwc&_journal_mode=WAL" 助手,将withNum词典引入作用域。

Num a

在我看来,即使名称{-# LANGUAGE GADTs, RankNTypes #-} data NumGadt a where NumGadt :: Num a => a -> Int -> String -> Bool -> NumGadt a withNum :: NumGadt a -> (Num a => b) -> b withNum (NumGadt _ _ _ _) y = y getNum :: NumGadt a -> a getNum (NumGadt a _ _ _) = a successor :: NumGadt a -> a successor x = withNum x (1 + getNum x) 更具自我说明性,这也不比与successor中的构造函数进行匹配要好得多。

请注意,您甚至可以使用较短的记录语法:

withNum