You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现支持异构返回类型的长度索引Vector的hMap函数?

解决异质函数向量的hMap实现问题

你遇到的核心问题是:你的Vector是同质向量(所有元素类型必须相同),但需求是处理异质函数(每个函数返回不同类型的结果),同质向量无法表达这种场景,必须改用异质向量(HVector),通过类型级列表来跟踪每个位置的具体类型。

为什么原代码无法编译

  1. 原Vector的设计要求所有元素类型一致,而forall b. a -> b是单一类型(能返回任意b的函数),但你实际需要的是每个位置的函数返回不同的b,这不是单一类型能表达的。
  2. Vec n (forall b. b)是逻辑上的空类型(没有任何值能满足这个类型),完全不符合你想要“每个位置对应不同结果类型”的需求。

解决方案:使用异质向量实现

首先需要启用GHC的依赖类型相关扩展,然后定义异质向量和对应的hMap函数。

完整实现代码

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE PolyKinds #-}

-- 异质向量:用类型级列表[Type]指定每个元素的类型
data HVec :: [Type] -> Type where
  HVNil  :: HVec '[]
  HVCons :: a -> HVec as -> HVec (a ': as)

-- 存放从统一输入类型a到不同输出类型的函数向量
data FunVec :: Type -> [Type] -> Type where
  FunNil  :: FunVec a '[]
  FunCons :: (a -> b) -> FunVec a bs -> FunVec a (b ': bs)

-- 实现hMap:将每个函数应用到输入值,生成对应类型的异质结果向量
hMap :: FunVec a bs -> a -> HVec bs
hMap FunNil _ = HVNil
hMap (FunCons f fs) x = HVCons (f x) (hMap fs x)

-- 示例使用:将输入5分别应用到+1、show、even三个函数
example :: HVec '[Int, String, Bool]
example = hMap (FunCons (+1) (FunCons show (FunCons even FunNil))) 5
-- 结果为:HVCons 6 (HVCons "5" (HVCons True HVNil))

代码说明

  1. HVec:异质向量的核心类型,它的类型参数是一个类型级列表(比如'[Int, String, Bool]),每个列表元素对应向量中对应位置的元素类型。
  2. FunVec:专门封装“输入类型统一为a,输出类型各异”的函数集合,让类型签名更直观,避免复杂的类型家族操作。
  3. hMap:递归遍历函数向量,将每个函数应用到输入值a,最终构造出对应类型的结果异质向量。

另一种实现:用类型家族简化

如果不想单独定义FunVec,可以用类型级Map函数直接在HVec上操作:

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE PolyKinds #-}

data HVec :: [Type] -> Type where
  HVNil  :: HVec '[]
  HVCons :: a -> HVec as -> HVec (a ': as)

-- 类型级Map:将函数类型(a ->)应用到类型列表的每个元素
type family Map (f :: k -> l) (xs :: [k]) :: [l] where
  Map f '[] = '[]
  Map f (x ': xs) = (f x) ': Map f xs

hMap :: forall a bs. HVec (Map (a ->) bs) -> a -> HVec bs
hMap HVNil _ = HVNil
hMap (HVCons f fs) x = HVCons (f x) (hMap fs x)

-- 示例使用
example :: HVec '[Int, String, Bool]
example = hMap (HVCons (+1) (HVCons show (HVCons even HVNil))) 5

这种方式直接用Map (a ->) bs表示“所有元素都是a -> b(其中b来自bs列表)”的异质函数向量,同样能实现需求。

内容的提问来源于stack exchange,提问作者John Smith

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 14:06:02