如何避免使用GADT实现多个功能?

som*_*unt 3 haskell gadt

首先,这是我的代码的最小示例:

{-# 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,那么就让我们吧.


Cir*_*dec 8

您的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)

  • 这是一个使用"幻像类型"的例子,以便您想要阅读更多内容. (3认同)