Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 使用类型族和泛型查找Id值_Haskell_Type Families_Ghc Generics - Fatal编程技术网

Haskell 使用类型族和泛型查找Id值

Haskell 使用类型族和泛型查找Id值,haskell,type-families,ghc-generics,Haskell,Type Families,Ghc Generics,这个问题涉及到,我想避免从数据结构中提取Id值的样板文件,但要以类型安全的方式 我将在这里重复问题的相关细节:假设您有一个类型Id: newtype Id = Id { _id :: Int } 您需要定义一个函数getId,该函数从至少包含一个Id值的任何结构中提取此Id: class Identifiable e where getId :: e -> Id 现在的问题是如何以类型安全的方式定义这样的类,同时使用泛型避免样板文件 在我的演讲中,我被指的是类型家族,尤其是思想

这个问题涉及到,我想避免从数据结构中提取
Id
值的样板文件,但要以类型安全的方式

我将在这里重复问题的相关细节:假设您有一个类型
Id

newtype Id = Id { _id :: Int }
您需要定义一个函数
getId
,该函数从至少包含一个
Id
值的任何结构中提取此
Id

class Identifiable e where
    getId :: e -> Id
现在的问题是如何以类型安全的方式定义这样的类,同时使用泛型避免样板文件

在我的演讲中,我被指的是类型家族,尤其是思想。据我所知,这个想法是定义一个类型类
mkidentification
,以便:

class MakeIdentifiable (res :: Res) e where
    mkGetId :: Proxy res -> e -> Id
其中,仅当至少有一个
Id
值嵌套在值的内部时,该值的类型为
Res

data Crumbs = Here | L Crumbs | R Crumbs
data Res = Found Crumbs | NotFound
然后,人们似乎可以定义:

instance MakeIdentifiable (Found e) e => Identifiable e where
    getId = mkGetId (Proxy :: Proxy (Found e))
现在的问题是如何为
Res
定义与GHC.泛型类型相关联的类型族(
U1
K1
:*:
:+:

我尝试了以下方法:

type family HasId e :: Res where
    HasId Id = Found Here
    HasId ((l :+: r) p) = Choose (HasId (l p)) (HasId (r p))
其中,
选择
类似于上述博文中的定义:

type family Choose e f :: Res where
    Choose (Found a) b = Found (L1 a)
    Choose a (Found b) = Found (R1 b)
    Choose a b = NotFound

但这不会编译为HasId(lp)具有kind
Res
,而是需要一个类型

您很快就可以进行
选择
打字检查了
L1
R1
(:+:)
的构造函数,而不是
Crumbs
。还有一个类型
GHC.Generics.R::*
,它在类型级别对
Crumbs
隐藏
R
构造函数,但是您可以使用
'R
消除歧义(单引号的名称是构造函数,双引号的名称是类型构造函数)

注释各种类型也是一种很好的做法,就像我们注释顶级函数的类型一样

type family Choose (e :: Res) (f :: Res) :: Res where
  Choose (Found a) b = Found ('L a)
  Choose a (Found b) = Found ('R b)
  Choose NotFound NotFound = NotFound  -- I'm not a fan of overlapping families

什么是
Choose
?我添加了
Choose
可能是什么的描述。