gpt4 book ai didi

generics - 使用标准的 haskell 泛型库进行类型化类型同构

转载 作者:行者123 更新时间:2023-12-03 14:15:13 31 4
gpt4 key购买 nike

仅在 Haskell 平台中就有几个具有许多重叠模块的泛型库( sybData.TypeableData.DataGHC.Generics ),但我在一个非常基本的泛型编程任务方面遇到了麻烦。

我希望能够在相同形状的类型之间进行转换,即我想要在同构类型之间进行多态、类型化的转换函数,基本上是在 this paper 末尾提供的功能(PDF) 其中提到了索引类型族。

我不关心废弃我的样板,而是能够围绕 sum 和 product 抽象构建新的库。

下面的问题是根据 GHC.Generic我认为这最接近我的需要,但欢迎使用其他解决方案。

以下两种形状相同

data Pair = Pair Char Int deriving (Generic, Show)
data Pair2 = Pair2 Char Int deriving (Generic, Show)

我想使用 GHC.Generics 在它们之间转换值。由于所有幻像参数和其他废话,以下内容无法进行类型检查:
f :: Pair -> Pair2
f = to . from

最终我想要一个类似于 fromInteger 的函数具有任何 Generic 的多态返回值(或任何其他类可以支持这个)实例。我想我正在寻找类似 GHC.Generics 的东西:
--class:
type family NormalForm a
class ToGeneric a where
to :: a -> NormalForm a
class FromGeneric b where
from :: NormalForm b -> b

--examples:
data A = A Char Int deriving Show
data B = B Char Int deriving Show

type instance NormalForm A = (Char,Int)
instance ToGeneric A where
to (A a b) = (a,b)
instance FromGeneric A where
from (a,b) = A a b

type instance NormalForm B = (Char,Int)
instance ToGeneric B where
to (B a b) = (a,b)
instance FromGeneric B where
from (a,b) = B a b

-- the function I'm looking for
coerce :: (ToGeneric a, FromGeneric b, NormalForm a ~ NormalForm b)=> a -> b
coerce = from . to

有了上面我们可以做我想做的一切:
*Main> (coerce $A 'a' 1) :: B
B 'a' 1
*Main> (coerce $A 'a' 1) :: A
A 'a' 1

编辑:这就是 Nathan Howell 的 f实际上,功能似乎在下面起作用。

问题
  • 这可能与目前在 haskell 平台上的库有关吗?
  • 如果没有,是否可以定义一个利用现有 deriving 的库? Generic 的机制, Data等,而不诉诸于 TH?
  • 最佳答案

    这是可能的,而且相对无痛。不像使用 unsafeCoerce直接,如果类型不对齐,您将获得构建中断。您可能可以依赖 f 上的等式约束。提供足够的编译时类型安全性以使用 unsafeCoerce并避免使用 Rep家庭。

    {-# LANGUAGE DeriveGeneric #-}
    {-# LANGUAGE TypeFamilies #-}

    import GHC.Generics

    data Pair1 = Pair1 Char Int deriving (Generic, Show)
    data Pair2 = Pair2 Char Int deriving (Generic, Show)

    data Triple1 = Triple1 Char Int Double deriving (Generic, Show)
    data Triple2 = Triple2 Char Int Double deriving (Generic, Show)

    f :: (Generic a, Generic c, Rep a ~ D1 da (C1 ca f), Rep c ~ D1 db (C1 cb f))
    => a -> c
    f = to . M1 . M1 . unM1 . unM1 . from
    -- this might also be acceptable:
    -- f = unsafeCoerce

    p1 :: Pair1 -> Pair2
    p1 = f

    p2 :: Pair2 -> Pair1
    p2 = f

    t1 :: Triple1 -> Triple2
    t1 = f

    t2 :: Triple2 -> Triple1
    t2 = f

    运行它会产生预期的结果:
    *Main> p1 $ Pair1 'x' 1
    Pair2 'x' 1
    *Main> p2 $ Pair2 'x' 1
    Pair1 'x' 1
    *Main> t1 $ Triple1 'y' 2 3.0
    Triple2 'y' 2 3.0
    *Main> t2 $ Triple2 'y' 2 3.0
    Triple1 'y' 2 3.0

    关于generics - 使用标准的 haskell 泛型库进行类型化类型同构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11887666/

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