haskell - 迭代具有不同输入和输出类型的函数
问题描述
我有两个函数可以将异构列表向右/向左旋转:
hRotateRight :: (HInit xs, HLast xs) => HList xs -> HList (HLastR xs ': HInitR xs)
hRotateRight xs = hLast xs `HCons` hInit xs
hRotateLeft :: HSnoc xs x => HList (x ': xs) -> HList (HSnocR xs x)
hRotateLeft (x `HCons` xs) = hSnoc xs x
显然,这两个函数都有不同的输入和输出类型(输入是单例时除外)。但是,它们确实具有函数的任何输出也可以是输入的特性,即函数可以迭代。
我正在寻找一种在 Haskell 中执行此操作的类型安全的方法(我不确定这是否可能)。谢谢!
解决方案
这是可能的,通常需要注意的是,Haskell 中的依赖类型编程一旦开始就会充满漏洞。
要多次迭代一个函数,我们首先需要一个数字的概念。最简单的表示是 Peano naturals,具有关联的单例类型,它提供与 type-level 链接的术语级值,Nat
而仅使用 term-level 是无法获得的Nat
。
data Nat = Z | S Nat
data SNat n where
SZ :: SNat 'Z
SS :: SNat n -> SNat ('S n)
在类型级别定义迭代旋转。
-- Note: some renaming happened, dropping type classes and reusing the simpler names for type families.
type Rotate1 xs = HLast xs ': HInit xs
type family RotateN n xs where
RotateN 'Z xs = xs
RotateN ('S n) xs = RotateN n (Rotate1 xs)
使用它,在术语级别定义迭代旋转,确保遵循与类型级别定义相同的“结构”。
hRotateN :: SNat n -> HList xs -> HList (RotateN n xs)
hRotateN SZ xs = xs
hRotateN (SS n) xs = hRotateN n (hRotateRight xs)
完整要点:https ://gist.github.com/Lysxia/fabbf6636f212577e89d507b5380f54d
另请参阅Justin Le 的博客系列介绍 Singletons 。
推荐阅读
- c# - C# 中的 MySQL:如何启用流量压缩?
- c# - 更改 Instagram 个人资料图片
- python - 如何检查类属性的设置器中的名称 isalpha() 是否?
- html - 如何删除 TWIG for Drupal 中的部分代码?
- java - 如何使用 apache camel 根据内容大小添加另一个 xml 标签
- python - 将 MacBook 更新到 macOS Catalina 后出现 Anaconda 问题
- python - Finding smallest entry in a dictionary, getting last key-value pair instead
- java - 如何使 Java 服务器从变量而不是控制台输入中读取?
- flutter - 使用 SelectableText (Flutter) 缺少 TextSpan 的 onTap 回调
- linux - 从 Windows 客户端连接到 Ubuntu 18.04,安装的 Samba 无法正常工作