这是示例代码:
{-# 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
但这非常丑陋,在更多地方使用它会变得非常丑陋。
问题是,有没有办法使编译器意识到这种类型只有一个构造函数,并从中推断出约束条件?
答案 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