是否可以编写
类型的内射函数hard :: (forall n . Maybe (f n)) -> Maybe (forall n . (f n))
作为total functional program - 也就是说,不使用error
,
undefined
,unsafeXXX
,bottom
,无穷无尽的模式,或任何
不终止的功能?
按parametricity,任何固定f :: *->*
的唯一总数
(forall n . Maybe (f n))
将采用以下两种形式之一:
Nothing
Just z
where
z :: forall n . f n
不幸的是,case
上Maybe
的所有尝试都需要
首先选择n
,然后选择模式变量的类型
案例分支在n
中将不再是多态的。好像是
语言缺少某种表现形式
case
- 对多态类型的歧视而不实例化
输入的
顺便说一句,在相反方向编写函数很容易:
easy :: Maybe (forall n . (f n)) -> (forall n . Maybe (f n))
easy Nothing = Nothing
easy (Just x) = Just x
答案 0 :(得分:4)
我恰巧得到了它,只是尝试创建一个我可以传递到见下面的评论。easyf
函数的值。如果你需要解释,我会遇到麻烦!!
data A α = A Int
data B f = B (forall α . f α)
a :: forall α . A α
a = A 3
b = B a
f (B (Just -> x)) = x -- f :: B t -> Maybe (forall α. t α)
f' (B x) = Just x -- f' :: B t -> Maybe (t α)
easy :: forall f . Maybe (forall n . (f n)) -> (forall n . Maybe (f n))
easy Nothing = Nothing
easy (Just x) = Just x
easyf :: Maybe (forall n . (A n)) -> (forall n . Maybe (A n))
easyf = easy
-- just a test
g = easyf (f b)
h :: (forall α. t α) -> Maybe (forall α. t α)
h = f . B
unjust :: (forall n . (Maybe (f n))) -> (forall n . f n)
unjust (Just x) = x
hard :: forall f. (forall n . (Maybe (f n))) -> Maybe (forall n . (f n))
hard xj@(Just _) = g (unjust xj) where
g :: (forall n . f n) -> Maybe (forall n . (f n))
g = h
hard Nothing = Nothing
从上面拿出垃圾,
mkJust :: (forall α. t α) -> Maybe (forall α. t α)
mkJust = Just
unjust :: (forall n . (Maybe (f n))) -> (forall n . f n)
unjust (Just x) = x
hard :: forall f. (forall n . (Maybe (f n))) -> Maybe (forall n . (f n))
hard xj@(Just _) = mkJust (unjust xj)
hard Nothing = Nothing
答案 1 :(得分:2)
我证明这是不可能的[错误,不,我没有;见Agda:
module Proof where
open import Data.Empty
open import Data.Maybe
open import Data.Bool
open import Data.Product
open import Relation.Nullary
open import Relation.Binary.PropositionalEquality
Type : Set₁
Type = Σ ({A : Set} {F : A → Set} → (∀ n → Maybe (F n)) → Maybe (∀ n → F n)) (λ f → ∀ {A} {F : A → Set} x y → f {F = F} x ≡ f y → (∀ i → x i ≡ y i))
helper : (b : Bool) → Maybe (T b)
helper true = just _
helper false = nothing
proof : ¬ Type
proof (f , pf) with inspect (f helper)
proof (f , pf) | just x with-≡ eq = x false
proof (f , pf) | nothing with-≡ eq with f {F = T} (λ _ → nothing) | pf helper (λ _ → nothing)
proof (f , pf) | nothing with-≡ eq | just x | q = x false
proof (f , pf) | nothing with-≡ eq | nothing | q with q eq true
proof (f , pf) | nothing with-≡ eq | nothing | q | ()
当然,这不是一个完美的反对,因为它是用不同的语言,但我认为它匹配得相当好。
我开始将Type
定义为你想要的函数的类型,同时证明函数是单射的(ΣxP可以看作是一个存在主义的说法“存在一个x,使得P(x)” )。因为我们讨论的是一个带有函数的内射函数(haskell的forall可以看作是一个类型级函数,而这就是它在Agda中的编码方式),我使用了逐点相等(∀ i → x i ≡ y i
),因为Agda的逻辑不会让我直接证明x ≡ y
。
除此之外,我只是通过对布尔值提供反例来反驳这种类型。
编辑:我刚刚意识到类型涉及从某种类型F
到类型的函数A
,因此我的证明与您在Haskell中编写的内容不完全对应。我现在很忙,但可能会稍后尝试解决这个问题。
编辑2:我的证明无效,因为我没有考虑参数。我可以在布尔上进行模式匹配,但不能在套装上进行模式匹配,我无法在Agda中证明这一点。我会更多地考虑这个问题:)
答案 2 :(得分:1)
如果您查看所有可能的计算依赖项,这很容易理解,每个计算值可能在运行时都有:
(forall n . Maybe (f n))
类型的表达式可以为一种类型评估为Nothing
,为另一种类型评估为Just
。因此,它是一个将类型作为参数的函数。
hard :: (forall n . Maybe (f n)) -> Maybe (forall n . f n)
-- problem statement rewritten with computational dependencies in mind:
hard' :: (N -> Maybe (fN)) -> Maybe (N -> fN)
Maybe (N -> fN)
类型的结果值(Nothing
或Just
)取决于N
的值(n
的类型)
所以答案是没有。
答案 3 :(得分:0)
问题可以简化为以下问题:我们可以编写一个以下列方式移动foralls的函数吗?
suicidal :: f (forall n. n) -> forall n. f n
毕竟,如果我们能够做到这一点,那么其余的很容易用一些不可预测的类型:
hard' :: Maybe (f (forall n. n)) -> Maybe (forall n. f n)
hard' Nothing = Nothing
hard' (Just x) = Just (suicidal x)
hard :: (forall n. Maybe (f n)) -> Maybe (forall n. f n)
hard x = hard' x -- instantiate 'n' at type 'forall n. n', thank goodness for impredicativity!
(如果您想在GHC中尝试此操作,请务必定义类似
的新类型newtype Forall f = Forall { unForall :: forall n. f n }
因为否则GHC喜欢将forall
漂浮到箭头前面并将你搞砸。)
但我们是否可以写suicidal
的答案很明确:不,我们不能!至少,不是以f
为参数的方式。解决方案必须看起来像这样:
suicidal x = /\ n. {- ... -}
...然后我们必须走过f
的“结构”,找到有类型函数的“地方”,然后将它们应用到我们现在可用的n
。关于hard
的原始问题的答案结果是相同的:我们可以针对任何特定hard
编写f
,但不会针对所有f
编写参数。
顺便说一句,我不相信你所说的关于参数的说法是对的:
通过参数化,对于任何固定
f :: *->*
,(forall n . Maybe (f n))
的唯一总居民将采用以下两种形式之一:Nothing
或Just z
其中z :: forall n . f n
。< / p>
实际上,我认为你得到的是居民(观察上等同于)两种形式之一:
/\ n. Nothing
/\ n. Just z
...上面的z
不多态:其具有特定类型f n
。 (注意:那里没有隐藏的forall
。)也就是说,后一种形式的可能术语取决于f
!这就是为什么我们不能以f
为参数编写函数。
编辑:顺便说一下,如果我们允许自己Functor
f
实例,那么事情当然更容易。
notSuicidal :: (forall a b. (a -> b) -> (f a -> f b)) -> f (forall n. n) -> forall n. f n
notSuicidal fmap structure = /\ n. fmap (\v -> v [n]) structure
...但这是作弊,尤其是因为我不知道如何将其转换为Haskell。 ; - )