这是玩具示例.hs:
{-# LANGUAGE ImpredicativeTypes #-}
import Control.Arrow
data From = From (forall a. Arrow a => a Int Char -> a [Int] String)
data Fine = Fine (forall a. Arrow a => a Int Char -> a () String)
data Broken = Broken (Maybe (forall a. Arrow a => a Int Char -> a () String))
fine :: From -> Fine
fine (From f) = Fine g
where g :: forall a. Arrow a => a Int Char -> a () String
g x = f x <<< arr (const [1..5])
broken :: From -> Broken
broken (From f) = Broken (Just g) -- line 17
where g :: forall a. Arrow a => a Int Char -> a () String
g x = f x <<< arr (const [1..5])
这就是ghci的想法:
GHCi, version 7.0.3: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
Prelude> :l toy-example.hs
[1 of 1] Compiling Main ( toy-example.hs, interpreted )
toy-example.hs:17:32:
Couldn't match expected type `forall (a :: * -> * -> *).
Arrow a =>
a Int Char -> a () String'
with actual type `a0 Int Char -> a0 () String'
In the first argument of `Just', namely `g'
In the first argument of `Broken', namely `(Just g)'
In the expression: Broken (Just g)
Failed, modules loaded: none.
为什么在fine
没有broken
时进行类型检查?
如何让broken
进行类型检查?
(在我的实际代码中,如果必须的话,我可以将类型参数a
添加到Broken
,而不是在构造函数中对其进行普遍量化,但我想尽可能避免这种情况。 。)
修改:如果我将Broken
的定义更改为
data Broken = Broken (forall a. Arrow a => Maybe (a Int Char -> a () String))
然后broken
类型检查。耶!
但如果我再添加以下功能
munge :: Broken -> String
munge (Broken Nothing) = "something" -- line 23
munge (Broken (Just f)) = f chr ()
然后我收到错误消息
toy-example.hs:23:15:
Ambiguous type variable `a0' in the constraint:
(Arrow a0) arising from a pattern
Probable fix: add a type signature that fixes these type variable(s)
In the pattern: Nothing
In the pattern: Broken Nothing
In an equation for `munge': munge (Broken Nothing) = "something"
如何让munge
同时进行类型检查?
第二次编辑:在我的真实程序中,我已将Broken (Maybe ...)
构造函数替换为BrokenNothing
和BrokenJust ...
构造函数(已有其他构造函数),但我我很好奇模式匹配在这种情况下应该如何工作。
答案 0 :(得分:2)
ImpredicativeTypes
让你处于非常不稳定的境地,无论如何都会从GHC版本变为版本 - 他们正在努力寻找一种适当平衡功能,易用性和易于实施的不可信度的表述。
在这种特殊情况下,尝试将量化类型放在Maybe
内,这是一种未明确定义的数据类型,这种方式非常棘手,因此我建议使用自定义构造函数相反,如你所说。
我认为你可以通过在RHS上重新解构munge
的参数来修复Broken
,当时使用它的类型将是已知,例如:
munge (Broken x@(Just _)) = fromJust x chr ()
但是,这很丑陋。