aem*_*xdp 13 haskell types higher-rank-types
是否有任何类型安全的方法来编写函数
bi f a b = (f a, f b)
Run Code Online (Sandbox Code Playgroud)
这样就可以像这样使用它:
x1 :: (Integer, Char)
x1 = bi head [2,3] "45"
x2 :: (Integer, Char)
x2 = bi fst (2,'3') ('4',5)
x3 :: (Integer, Double)
x3 = bi (1+) 2 3.45
Run Code Online (Sandbox Code Playgroud)
?在rank-n-types例子中总有一些更简单的东西
g :: (forall a. a -> a) -> a -> a -> (a, a)
g f a b = (f a, f b)
Run Code Online (Sandbox Code Playgroud)
{-# LANGUAGE TemplateHaskell #-}
bi f = [| \a b -> ($f a, $f b)|]
Run Code Online (Sandbox Code Playgroud)
ghci> :set -XTemplateHaskell
ghci> $(bi [|head|]) [2,3] "45"
(2,'4')
Run Code Online (Sandbox Code Playgroud)
;)
是的,尽管不是在 Haskell 中。但高阶多态 lambda 演算(又名系统 F-omega)更为通用:
bi : forall m n a b. (forall a. m a -> n a) -> m a -> m b -> (n a, n b)
bi {m} {n} {a} {b} f x y = (f {a} x, f {b} y)
x1 : (Integer, Char)
x1 = bi {\a. List a} {\a. a} {Integer} {Char} head [2,3] "45"
x2 : (Integer, Char)
x2 = bi {\a . exists b. (a, b)} {\a. a} {Integer} {Char} (\{a}. \p. unpack<b,x>=p in fst {a} {b} x) (pack<Char, (2,'3')>) (pack<Integer, ('4',5)>)
x3 : (Integer, Double)
x3 = bi {\a. a} {\a. a} {Integer} {Double} (1+) 2 3.45
Run Code Online (Sandbox Code Playgroud)
在这里,我f {T}为显式类型应用程序编写并假设分别类型化的库。类似于\a. a类型级别的 lambda。这个x2例子更加复杂,因为它还需要存在类型来本地“忘记”参数中的其他多态性。
实际上,您可以在 Haskell 中模拟这一点,方法是newtype为实例化的每个不同的 or 定义一个 or 数据类型m,n并传递适当包装的函数f来相应地添加和删除构造函数。但显然,这一点也不好玩。
编辑:我应该指出,这仍然不是一个完全通用的解决方案。例如,我不知道你如何输入
swap (x,y) = (y,x)
x4 = bi swap (3, "hi") (True, 3.1)
Run Code Online (Sandbox Code Playgroud)
即使在 F-omega 系统中也是如此。问题在于该swap函数比 allowed 具有更多的多态性bi,并且与 with 不同x2,结果中不会忘记另一个多态维度,因此存在主义技巧不起作用。看来您需要一种多态性来允许这种情况(以便参数可以bi在不同数量的类型上具有多态性)。
| 归档时间: |
|
| 查看次数: |
477 次 |
| 最近记录: |