gpt4 book ai didi

haskell - 是否可以删除此 DataKinds 支持的异构列表实现的 OverlappingInstances?

转载 作者:行者123 更新时间:2023-12-02 17:16:34 27 4
gpt4 key购买 nike

通过最近有关 HaskellDB 的帖子,我有动力再次研究 HList。由于我们现在在 GHC 中有 -XDataKinds,它实际上有一个异构列表的示例,因此我想研究 HList 与 DataKinds 的关系。到目前为止,我有以下内容:

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverlappingInstances #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}

import Data.Tagged

data Record :: [*] -> * where
RNil :: Record '[]
(:*:) :: Tagged f (FieldV f) -> Record t -> Record (f ': t)

type family FieldV a :: *

emptyRecord = RNil

(=:) :: (v ~ FieldV f) => f -> v -> Tagged f v
f =: v = Tagged v

class HasField x xs where
(=?) :: Record xs -> x -> FieldV x

instance HasField x (x ': xs) where
(Tagged v :*: _) =? _ = v

instance HasField x xs => HasField x (a ': xs) where
(_ :*: r) =? f = r =? f

--------------------------------------------------------------------------------
data EmployeeName = EmployeeName
type instance FieldV EmployeeName = String

data EmployeeID = EmployeeID
type instance FieldV EmployeeID = Int

employee = (EmployeeName =: "James")
:*: ((EmployeeID =: 5) :*: RNil)

employeeName = employee =? EmployeeName
employeeId = employee =? EmployeeID

这按预期工作,但我在这个项目中的目标是尝试尽可能在没有类型类的情况下完成它。所以这里有2个问题。首先,是否可以在没有类型类的情况下编写 (=?) (记录字段访问器函数)?如果没有的话,可以写成没有重叠实例吗?

我想我的第一个问题是不可能的,但第二个问题也许是可能的。我很想听听人们的想法!

最佳答案

我认为这两个问题的答案都是肯定的。您根本无法拥有以下形式的类型函数

type family TypeEq a b :: Bool
type instance TypeEq a a = True
type instance TypeEq a b = False

这本质上就是 OverlappingInstances 为您提供的。 Oleg 建议使用类型级别 TypeReps 的替代机制,但我们还没有。这个答案是合格的,因为您确实有丑陋“解决方案”,例如使用可键入的

{-# LANGUAGE DataKinds, GADTs, DeriveDataTypeable, TypeFamilies, TypeOperators #-}

import Data.Typeable

type family FieldV a :: *

data FieldOf f where
FieldOf :: FieldV f -> FieldOf f

(=:) :: f -> FieldV f -> FieldOf f
_ =: v = FieldOf v

fromField :: FieldOf f -> FieldV f
fromField (FieldOf v) = v

data Record :: [*] -> * where
RNil :: Record '[]
(:*:) :: Typeable f => FieldOf f -> Record t -> Record (f ': t)

data SameType a b where
Refl :: SameType a a

useProof :: SameType a b -> a -> b
useProof Refl a = a

newtype SF a b = SF (SameType (FieldOf a) (FieldOf b))
sf1 :: FieldOf f -> SF f f
sf1 _ = SF Refl

targetType :: f -> Maybe (SF g f)
targetType _ = Nothing

(?=) :: Typeable a => Record xs -> a -> Maybe (FieldV a)
RNil ?= _ = Nothing
(x :*: xs) ?= a = case (gcast (sf1 x)) `asTypeOf` (targetType a) of
Nothing -> xs ?= a
Just (SF y) -> Just . fromField $ useProof y x

x =? v = case x ?= v of
Just x -> x
Nothing -> error "this implementation under uses the type system"

data EmployeeName = EmployeeName deriving Typeable
type instance FieldV EmployeeName = String

data EmployeeID = EmployeeID deriving Typeable
type instance FieldV EmployeeID = Int

employee = (EmployeeName =: "James")
:*: ((EmployeeID =: 5) :*: RNil)

employeeName = employee =? EmployeeName
employeeId = employee =? EmployeeID

这显然不如基于类型类的版本。但是,如果您可以接受一点动态输入...

关于haskell - 是否可以删除此 DataKinds 支持的异构列表实现的 OverlappingInstances?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12124584/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com