首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在HList上编写异构列表?

如何在HList上编写异构列表?
EN

Stack Overflow用户
提问于 2022-03-01 06:30:43
回答 2查看 144关注 0票数 3

我想使用HList:异构列表

安装了库之后,import Data.HList (HList)已经完成了。

现在,研究https://bitbucket.org/HList/hlist/src/master/examples/HListExample/并不能帮助我开始编写代码。

我想做的是,

  1. 创建像H[1, "2"]这样的hello-world异构列表(根本不确定语法)
  2. 将异构列表映射到每个print

有没有人熟悉如何使用HList

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-03-01 13:47:10

您可能不想只在HList上映射,而是遍历它,也就是mapM。而且您可能对不可分割的结果不感兴趣--()s,但是只对副作用感兴趣,所以那将是mapM_

HList确实有一个通用的工具,叫做hMapM_。将它与任意约束的多态函数一起使用有点复杂,但是对于具体的打印,这实际上是随库准备好使用的:

代码语言:javascript
运行
复制
Prelude Data.HList> let l = 1.*."2".*.HNil :: HList '[Int, String]
Prelude Data.HList> l
H[1,"2"]
Prelude Data.HList> hMapM_ HPrint l
1
"2"

如前所述,将其与其他多态函数(无需编写自定义类型)一起使用的方法是使用Fun,如下所示

代码语言:javascript
运行
复制
Prelude Data.HList> hMapM_ (Fun print :: Fun Show (IO ())) l
1
"2"

...which并不是太尴尬,但还是有点烦人。我定义了一个同义词,它允许用TypeApplications编写这篇文章,以避免冗余:

代码语言:javascript
运行
复制
{-# LANGUAGE TypeFamilies, RankNTypes, ConstraintKinds, UnicodeSyntax #-}

import Data.Kind

fun :: ∀ (cxt :: Type -> Constraint) getb
        . (∀ a. (cxt a) => a -> getb) -> Fun cxt getb
fun = Fun

然后

代码语言:javascript
运行
复制
Prelude Data.HList Data.Kind> :set -XTypeApplications
Prelude Data.HList Data.Kind> hMapM_ (fun @Show print) l
1
"2"

或者我们甚至可以做到

代码语言:javascript
运行
复制
{-# LANGUAGE FlexibleContexts, AllowAmbiguousTypes #-}

h'MapM_ :: ∀ (cxt :: Type -> Constraint) l m
   . (Monad m, HFoldr (Mapcar (Fun cxt (m ()))) [m ()] l [m ()])
    => (∀ a. (cxt a) => a -> m ()) -> HList l -> m ()
h'MapM_ f = hMapM_ (Fun f :: Fun cxt (m ()))

然后

代码语言:javascript
运行
复制
Prelude Data.HList Data.Kind> h'MapM_ @Show print l
1
"2"
票数 5
EN

Stack Overflow用户

发布于 2022-03-01 09:10:02

您可以通过使用HList和hBuild函数来构造hEnd,例如:

代码语言:javascript
运行
复制
hello = hEnd (hBuild 1 "2")

在这个列表上映射print要困难得多。我认为编写一个能够在print上映射HList的高阶函数是不容易的,但是您可以像这样手动遍历HList:

代码语言:javascript
运行
复制
{-# LANGUAGE DataKinds #-}

import Data.HList

class PrintEach ts where
  printEach :: HList ts -> IO ()
instance PrintEach '[] where
  printEach HNil = pure ()
instance (Show t, PrintEach ts) => PrintEach (t : ts) where
  printEach (HCons x xs) = print x *> printEach xs

hello = hEnd (hBuild 1 "2")

main = printEach hello
-- This prints:
-- 1
-- "2"
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71304552

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档