Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ajax/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 如何在存在包装器下应用任意函数?_Haskell_Existential Type - Fatal编程技术网

Haskell 如何在存在包装器下应用任意函数?

Haskell 如何在存在包装器下应用任意函数?,haskell,existential-type,Haskell,Existential Type,我正在尝试编写一个函数(这里称为hide),它可以在存在包装器中应用一个足够多态的函数(或者提升函数来处理隐藏类型的包装器;因此称为“hide”): 所以我很理解为什么会这样works显示当返回类型与输入类型完全无关时,hide实际上起作用,但在中不起作用我正在调用hide,参数类型为a->[a]hide应该可以“选择”类型a(RankNTypes),但是b通常是多态的。当b实际上依赖于a时,a可能泄漏 但在我实际调用它的上下文中,a实际上并没有泄漏出来;我立即用Some把它包起来。事实上,我可

我正在尝试编写一个函数(这里称为
hide
),它可以在存在包装器中应用一个足够多态的函数(或者提升函数来处理隐藏类型的包装器;因此称为“hide”):

所以我很理解为什么会这样
works
显示当返回类型与输入类型完全无关时,
hide
实际上起作用,但在
中不起作用
我正在调用
hide
,参数类型为
a->[a]
hide
应该可以“选择”类型
a
RankNTypes
),但是
b
通常是多态的。当
b
实际上依赖于
a
时,
a
可能泄漏

但在我实际调用它的上下文中,
a
实际上并没有泄漏出来;我立即用
Some
把它包起来。事实上,我可以编写一个替代的
hide'
,它专门接受
a->[a]
函数,并使用完全相同的实现,只是一个不同类型的签名

是否有任何方法可以键入实现
hide f(Some x)=Some(fx)
,使其更通用?实际上,我对类型为
a->qa
的提升函数感兴趣,其中
q
是一些任意类型的函数;i、 e.我希望返回类型依赖于
a
,但我不在乎它是如何实现的。可能存在
qa
为常数的用例(即返回类型不依赖于
a
),但我认为它们将更为罕见

显然,这个例子很愚蠢。在我的实际用例中,我有一个GADT
模式a
,粗略地说,它表示外部类型系统中的类型;phantom参数提供了一个Haskell类型,可用于表示外部类型系统中的值。我需要幻影参数来保证所有类型的安全,但有时我会基于运行时数据构造
Schema
s,在这种情况下,我不知道该参数的类型是什么


因此,我似乎需要另一个类型,它与类型参数无关。我希望使用一个简单的存在包装器,比如
Some
,从
Schema
构建它,并能够为所有a类提升
类型的函数,而不是(仍然)创建另一个并行类型。模式a->模式b
一些模式->一些模式
。因此,如果我有一个XY问题,我最好使用一些其他方法来传递未知的
a
模式a,这也会解决我的问题。

正如David Young所说,你可以写

hide' :: (forall a. f a -> g (q a)) -> Some f -> Some g
hide' f (Some x) = Some (f x)

does :: Functor f => Some f -> Some f
does = hide' (fmap (:[]))
但是,您可以将其绑定为如下方式,而不是将
hide
fmap设置为类似:

hide'' :: (forall a. f a -> Some g) -> Some f -> Some g
hide'' f (Some x) = f x

does :: Functor f => Some f -> Some f
does = hide'' (Some . fmap (:[]))
但这有点陈词滥调

或者更一般地说

elim :: (forall a. f a -> c) -> Some f -> c
elim f (Some x) = f x

我不确定这对您的更大用例有多大用处,因为您必须重构所有现有操作以使用延续传递样式,但延续可以用于实现一个
隐藏
,它对您的两个示例都有效,并使
b
完全通用

hide :: (forall r a. f a -> (forall b. g b -> r g) -> r g) -> Some f -> Some g
hide f (Some x) = f x Some

cast :: Phantom a -> (forall b. Phantom b -> r Phantom) -> r Phantom
cast Phantom f = f Phantom

works :: Some Phantom -> Some Phantom
works = hide cast

alsoWorks :: Functor f => Some f -> Some f
alsoWorks = hide (\a f -> f $ fmap (\x -> [x]) a)
通过分解CPS转换,您可以更轻松地使用现有函数,如原始的
cast
,从而使它变得更好:

hide :: (forall r a. f a -> (forall b. g b -> r g) -> r g) -> Some f -> Some g
hide f (Some x) = f x Some

cps :: (f a -> g b) -> (f a -> (forall c. g c -> r) -> r)
cps f a c = c (f a)

cast :: Phantom a -> Phantom b
cast Phantom = Phantom

works :: Some Phantom -> Some Phantom
works = hide $ cps cast

alsoWorks :: Functor f => Some f -> Some f
alsoWorks = hide $ cps $ fmap (\x -> [x])

如果你把它键入
hide::(对于所有的a.fa->g(qa))->Some f->Some g
不会进行类型检查,但这可能不像你想要的那样一般(当
q~Id
时,你不能使用它,比如
type Id a=a
。@davidyong我会试试看怎么做;我不太希望它作为一个组合器向我的库的用户公开,但它很可能满足我的大多数内部需求(因为为了在
a
中具有足够的多态性,我通常只是将它包装成其他多态性)。此外,我不确定这些是否对解决这个问题有很大帮助,但这类事情让我想起了我开始为研究存在主义而开发的这个软件包(不过现在主要集中在存在主义列表上):。底部注释掉的内容可能最适用于此(特别是,我想到了多类
Functor
类的
Existential
实例),但它可能还不起作用(但我不完全记得)。我非常喜欢
elim
。它在一定程度上违背了本文的目的,因为我的目标是使用一个组合器,将现有的
Schema a->Schema b
操作提升到
Some Schema->Some Schema
操作,因此我不必在任何地方手动展开和重写
Some
elim
使我不必手动展开,但不必重新包装。@Ben,您还可以定义同义词,如
sfmap f=Some。fmap f
。我认为在大多数情况下,
hide'
就足够了。
q~Id
的问题(除了您可以定义另一个
hide::(对于所有a.f a->g a)->一些f->一些g)
可以通过将
Id
定义为
newtype
来解决,但代价是相同的包装-展开。re
sfmap
:True,但是,重新定义我的每一个函数的存在风格版本是我可以做的事情,而不需要任何版本的
hide
;只需为我感兴趣的每个
f
f'(Some x)=Some(fx)
hide :: (forall r a. f a -> (forall b. g b -> r g) -> r g) -> Some f -> Some g
hide f (Some x) = f x Some

cps :: (f a -> g b) -> (f a -> (forall c. g c -> r) -> r)
cps f a c = c (f a)

cast :: Phantom a -> Phantom b
cast Phantom = Phantom

works :: Some Phantom -> Some Phantom
works = hide $ cps cast

alsoWorks :: Functor f => Some f -> Some f
alsoWorks = hide $ cps $ fmap (\x -> [x])