简体   繁体   English

如何投射`forall a。 a -> a` 回到 `a -> a`?

[英]How to cast `forall a. a -> a` back to `a -> a`?

In my actual problem I have a function f , passed as a parameter, that changes the order in a list but has no requirements regarding type and does not change the type either.在我的实际问题中,我有一个函数f ,作为参数传递,它改变了列表中的顺序,但对类型没有要求,也不改变类型。 I want to apply that function on [Int] and [Bool] so I have to resolve both contexts trying to typecast f to either [Int] -> [Int] or [Bool] -> [Bool] .我想在[Int][Bool]上应用该函数,所以我必须解决试图将f类型转换为[Int] -> [Int][Bool] -> [Bool]两个上下文。 I solved this with Rank2Types .我用Rank2Types解决了这个Rank2Types But then I use any on a list of functions like f and any requires the functions to be [a] -> [a] rather than forall a. [a] -> [a]但是随后我在f等函数列表中使用any ,并且any要求函数为[a] -> [a]而不是forall a. [a] -> [a] forall a. [a] -> [a] . forall a. [a] -> [a]

The code below while nonsensical perfectly reproduces the error:下面的代码虽然荒谬,但完美地重现了错误:

{-# LANGUAGE Rank2Types #-}

--debug :: (forall a. [a] -> [a]) -> Bool 
debug swap = any combine [swap]
  where
    combine :: (forall a. [a] -> [a]) -> Bool
    combine f =  usefonBool f && usefonInt f
    --usefonBool :: (forall a. [a] -> [a]) -> Bool
    usefonBool f = f [True,True] == [False]

    --usefonInt :: (forall a. [a] -> [a]) -> Bool
    usefonInt f = (f [1,2]) == [2,1]

The error message is:错误信息是:

• Couldn't match type ‘a’ with ‘forall a1. [a1] -> [a1]’
  ‘a’ is a rigid type variable bound by
    the inferred type of debug :: a -> Bool
    at /path/debug.hs:(4,1)-(12,36)
  Expected type: a -> Bool
    Actual type: (forall a. [a] -> [a]) -> Bool
• In the first argument of ‘any’, namely ‘combine’
  In the expression: any combine [swap]
  In an equation for ‘debug’:
      debug swap
        = any combine [swap]
        where
            combine :: (forall a. [a] -> [a]) -> Bool
            combine f = usefonBool f && usefonInt f
            usefonBool f = f [True, ....] == [False]
            usefonInt f = (f [1, ....]) == [2, ....]
• Relevant bindings include
    swap :: a (bound at /path/debug.hs:4:7)
    debug :: a -> Bool (bound at /path/debug.hs:4:1)
|

My goal is to find an annotation that lets me use an f on different types and then apply any on a list of such generic functions.我的目标是找到一个注释,让我可以在不同类型上使用f ,然后将 any 应用于此类通用函数的列表。

If I uncomment all my type annotations (or just the top one) the error changes to如果我取消注释所有类型注释(或只是顶部注释),错误将更改为

• Couldn't match type ‘[a0] -> [a0]’ with ‘forall a. [a] -> [a]’
  Expected type: ([a0] -> [a0]) -> Bool
    Actual type: (forall a. [a] -> [a]) -> Bool
• In the first argument of ‘any’, namely ‘combine’
  In the expression: any combine [swap]
  In an equation for ‘debug’:
      debug swap
        = any combine [swap]
        where
            combine :: (forall a. [a] -> [a]) -> Bool
            combine f = usefonBool f && usefonInt f
            usefonBool :: (forall a. [a] -> [a]) -> Bool
            usefonBool f = f [True, ....] == [False]
            ....
  |

First, note that Rank2Types is a deprecated name.首先,请注意Rank2Types是一个已弃用的名称。 It's equivalent to RankNTypes in modern GHC, and that's the preferred name for the extension.它相当于现代 GHC 中的RankNTypes ,这是扩展的首选名称。

Here's the underlying problem.这是根本的问题。 A "list of such generic functions" could have the type: “此类通用函数的列表”可以具有以下类型:

[forall a. [a] -> [a]]

Sadly, this isn't a valid Haskell type because Haskell doesn't support "impredicative polymorphism".遗憾的是,这不是有效的 Haskell 类型,因为 Haskell 不支持“不可预测的多态性”。 Specifically, the following program:具体来说,以下程序:

{-# LANGUAGE RankNTypes #-}
myFunctions :: [forall a. [a] -> [a]]
myFunctions = [f1, f2]
   where f1 (x:y:rest) = y:x:rest
         f2 = reverse

produces the error message:产生错误信息:

 DebugRank.hs:2:16: error: • Illegal polymorphic type: forall a. [a] -> [a] GHC doesn't yet support impredicative polymorphism • In the type signature: myFunctions :: [forall a. [a] -> [a]]

There's an extension, ImpredicativeTypes .有一个扩展, ImpredicativeTypes It's flakey and incomplete, but it allows the following to compile:它不完整且不完整,但它允许编译以下内容:

{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE ImpredicativeTypes #-}

myFunctions :: [forall a. [a] -> [a]]
myFunctions = [f1, f2]
   where f1 (x:y:rest) = y:x:rest
         f2 = reverse

debug :: [forall a. [a] -> [a]] -> Bool
debug = any combine
  where
    combine :: (forall a. [a] -> [a]) -> Bool
    combine f = usefonBool f && usefonInt f
    usefonBool f = f [True,True] == [False]
    usefonInt  f = f [1,2] == [2,1]

main = print (debug myFunctions)

I'd still recommend against using it, though.不过,我仍然建议不要使用它。

The usual alternative is to use a newtype wrapper for the polymorphic function:通常的替代方法是对多态函数使用newtype包装器:

newtype ListFunction = ListFunction (forall a. [a] -> [a])

This requires some boilerplate, but no extensions other than RankNTypes :这需要一些样板,但除了RankNTypes之外没有扩展:

myFunctions :: [ListFunction]
myFunctions = [ListFunction f1, ListFunction f2]
   where f1 (x:y:rest) = y:x:rest
         f2 = reverse

debug :: [ListFunction] -> Bool
debug = any combine
  where
    combine :: ListFunction -> Bool
    combine (ListFunction f) = usefonBool f && usefonInt f
    usefonBool f = f [True,True] == [False]
    usefonInt  f = f [1,2] == [2,1]

The complete code:完整代码:

{-# LANGUAGE RankNTypes #-}

newtype ListFunction = ListFunction (forall a. [a] -> [a])

myFunctions :: [ListFunction]
myFunctions = [ListFunction f1, ListFunction f2]
   where f1 (x:y:rest) = y:x:rest
         f2 = reverse

debug :: [ListFunction] -> Bool
debug = any combine
  where
    combine :: ListFunction -> Bool
    combine (ListFunction f) = usefonBool f && usefonInt f
    usefonBool f = f [True,True] == [False]
    usefonInt  f = f [1,2] == [2,1]

main = print $ debug myFunctions

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 forall a之间有什么区别? [a]和[forall a。一个]? - What is the difference between forall a. [a] and [forall a. a]? 为什么是 `[1, "a"] :: [forall a. 不允许显示 a => a]`? - Why is `[1, "a"] :: [forall a. Show a => a]` not allowed? 使用量化约束导出 Ord(forall a.Ord a => Ord (fa)) - Derive Ord with Quantified Constraints (forall a. Ord a => Ord (f a)) 为什么是forall a。 一个不被认为是Int的子类型,而我可以使用类型forall a的表达式。 预计会有任何一种类型的Int? - Why is forall a. a not considered a subtype of Int while I can use an expression of type forall a. a anywhere one of type Int is expected? 为什么id的类型不能专门用于(forall a.a - > a) - >(forall b.b - > b)? - Why can't the type of id be specialised to (forall a. a -> a) -> (forall b. b -> b)? 翻译/编码Haskell的`data Obj = forall a。 (显示a)=> Scala中的Obj a` - Translate/encode Haskell's `data Obj = forall a. (Show a) => Obj a` in Scala 如何将Dynamic转换为Forall的东西 - How to convert Dynamic to Forall something 如何理解类型 a 和 forall r。 (a -> r) -> r 是同构的 - How to understand that the types a and forall r. (a -> r) -> r are isomorphic 斯卡拉的forall - forall in Scala Forall约束 - Forall constraints
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM