我不确定为什么k4
下面的k3
不起作用,ghci
确实如此,其足够的多态性。 • Couldn't match type ‘K' a0 a0’ with ‘End K'’
Expected type: K' a0 a0 -> K'' a a
中的错误是
{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE GADTs #-} #!/usr/bin/env stack -- stack --install-ghc --resolver lts-8.21 runghc --package http-conduit --package lens {-# LANGUAGE ExistentialQuantification, RankNTypes #-} module YonedaLan where type End g = forall a. g a a data K' b c = K' data K'' b c = K'' k1 :: () -> End K' k1 x = K' k2 :: End K' -> End K'' k2 x = case x of (K') -> K'' k3 :: () -> End K'' k3 x = k2 ( k1 x) k4 :: () -> End K'' k4 = k2 . k1
Toast.makeText(getApplicationContext(), "Authentication failed!" , Toast.LENGTH_SHORT).show();
除了不写自由风格之外,还有一些最佳实践可以解决这个问题吗?
答案 0 :(得分:4)
问题是GHC类型系统永远不会将类型变量实例化为多态类型。这样做需要类型系统中的不可靠性。
在你的具体例子中,我们有
(.) :: (b->c) -> (a->b) -> (a->c)
并且,要键入check k2 . k1
,我们需要实例化b ~ End K'
这是一种多态类型。
典型的解决方法是将End K'
转换为包含多态类型的单态类型。 E.g。
newtype End g = End { unEnd :: forall a. g a a }
要付出的代价是在每次使用时明确包装/解包类型End g
的值。这也可以通过GHC的安全强制来减轻这种情况。
请注意,其他一些语言(如Agda,Coq,Idris)会很好地处理您的代码(适当翻译),因为它们具有不可预测的类型系统。然而,他们的推理机制与Haskell不同 - 不确定性使其变得更加困难。有时,如果不经常,类型推理引擎无法找到隐式类型参数,并且必须明确提供类型。