首先,这是我的代码的最小示例:
{-# LANGUAGE GADTs #-}
-- package "url"
import Network.URL (exportURL, URL(..), URLType(..))
data MyURL a where
GalleryURL :: URL -> MyURL URL
PictureURL :: URL -> MyURL URL
url = URL { url_type = PathRelative,
url_path = "www.google.com",
url_params = []}
galleryURL = GalleryURL url
myExportURL :: MyURL a -> String
myExportURL (GalleryURL a) = exportURL a
myExportURL (PictureURL a) = exportURL a
main = print $ myExportURL galleryURL
Run Code Online (Sandbox Code Playgroud)
我使用GADT来避免混合不同类型的URL.myExportURL所有类型的URL 的功能都相同.有没有办法使用这样的东西:
myExportURL (_ a) = exportURL a
Run Code Online (Sandbox Code Playgroud)
而不是为GADT的每个子类型(正确的术语是什么?)重复它?
关于代码或我想解决的问题的任何其他评论也是受欢迎的.
npo*_*cop 12
正确的术语是"为每个构造函数".
您的GADT看起来很可疑,因为所有构造函数都构造相同的MyURL URL类型.如果这就是你想要的,那么你首先不需要GADT并且可以使用普通的ADT:
data MyURL = GalleryURL URL | PictureURL URL
Run Code Online (Sandbox Code Playgroud)
要缩短myExportUrl,有不同的选择.一种是重构类型:
data URLKind = GalleryURL | PictureURL
data MyURL = MyURL { myUrlKind :: URLKind, myExportURL :: URL }
Run Code Online (Sandbox Code Playgroud)
这样你仍然可以使用"短"结构形式,例如MyURL PictureURL foo.而且你也可以使用myExportURLHaskell为你生成的函数.
只有在高级情况下才需要GADT,所以如果你的例子没有充分证明你为什么需要GADT,那么就让我们吧.
您的MyURL类型不会阻止您混合图库和图片URL.GalleryURL和PictureURL都具有相同的类型MyURL URL.尝试这样的事情:
data Gallery = Gallery
data Picture = Picture
data MyURL a where
MyURL :: a -> URL -> MyURL a
Run Code Online (Sandbox Code Playgroud)
然后你可以像想象的那样编写代码的其余部分:
url = URL { url_type = PathRelative,
url_path = "www.google.com",
url_params = []}
galleryURL = MyURL Gallery url
myExportURL :: MyURL a -> String
myExportURL (MyURL _ a) = exportURL a
main = print $ myExportURL galleryURL
Run Code Online (Sandbox Code Playgroud)
当所有构造函数适用于所有类型时,您不需要GADT,并且您不需要Gallery和Picture类型的构造函数,因此您可以将这些部分编写为:
data Gallery -- requires the empty type extension
data Picture
data MyURL a = MyURL URL
galleryURL :: MyURL Gallery
galleryURL = MyURL url
myExportURL :: MyURL a -> String
myExportURL (MyURL a) = exportURL a
Run Code Online (Sandbox Code Playgroud)