其他人建议修改数据结构,这是使用模式同义词的不同方法:
{-# Language GADTs, PatternSynonyms, ViewPatterns, TypeOperators #-}
import Data.Kind
data MyURL a where
GalleryURL :: URL -> MyURL URL
PictureURL :: URL -> MyURL URL
url :: MyURL a -> URL
url (GalleryURL u) = u -- Proof that: URL ~ a
url (PictureURL u) = u -- Proof that: URL ~ a
-- Works on ‘MyURL a’ for any ‘a’
pattern Url :: URL -> MyURL a
pattern Url u <- (url -> u)
如果添加另一个不包含 a 的构造函数,URL
我们必须为url
data MyURL a where
GalleryURL :: URL -> MyURL URL
PictureURL :: URL -> MyURL URL
I :: Int -> MyURL Int
url :: MyURL a -> Maybe URL
url (GalleryURL u) = Just u -- Proof that: URL ~ a
url (PictureURL u) = Just u -- Proof that: URL ~ a
url (I i) = Nothing -- Proof that: Int ~ a
pattern Url :: URL -> MyURL a
pattern Url u <- (url -> Just u)
showMyURL :: MyURL a -> String
showMyURL (Url u) = show u
showMyURL (I i) = show i -- Proof that: Int ~ a
然而!— 假设我们想要一个在给定时返回 an 的评估函数a
—MyURL a
这按预期工作
eval :: MyURL a -> a
eval (GalleryURL url) = url -- Proof that: URL ~ a
eval (PictureURL url) = url -- Proof that: URL ~ a
eval (I int) = int -- Proof that: Int ~ a
但是我们的新Url
模式同义词失败了!
eval :: MyURL a -> a
eval (Url url) = url
我们没有得到关于何时对模式同义词进行模式匹配的新信息a
pattern Url :: URL -> MyURL a
a
和之间的联系URL
已被切断。我们导入Data.Type.Equality并添加一个等于的Refl :: a :~: URL
证明:a
URL
-- Gets ‘URL’ from a ‘MyURL URL’
--
-- ‘Refl’ is our proof that the input is ‘MyURL URL’
url :: MyURL a -> Maybe (a :~: URL, a)
url (GalleryURL url) = Just (Refl, url)
url (PictureURL url) = Just (Refl, url)
url (I int) = Nothing
然后我们说这Url _
提供了一个证明,a ~ URL
当匹配时,
pattern Url :: () => a ~ URL => a -> MyURL a
pattern Url url <- (Url -> (Refl, url))
并且URL
可以再次使用单个模式检索
eval :: MyURL a -> a
eval (Url url) = url -- Proof that: URL ~ a
eval (I int) = int -- Proof that: Int ~ a