{-# LANGUAGE
NoImplicitPrelude,
MultiParamTypeClasses,
FlexibleInstances, FlexibleContexts,
TypeFamilies, UndecidableInstances,
AllowAmbiguousTypes
#-}
import Prelude(Char, Show, show, undefined, id)
data Nil
nil :: Nil
nil = undefined
instance Show Nil where
show _ = "nil"
data Cons x xs = Cons x xs
deriving Show
class FPack f r where
fpack :: f -> r
instance {-# OVERLAPPABLE #-} f ~ (Nil -> r) => FPack f r where
fpack f = f nil
instance (FPack (x -> b) r, f ~ (Cons a x -> b)) => FPack f (a -> r) where
fpack f a = fpack (\x -> f (Cons a x))
fpack id "a" "b" :: Cons [Char] (Cons [Char] Nil)
生成列表Cons“a”(Cons“b”nil)
。
通常,我希望通过传递id
作为其f
参数(如上)来调用fpack
,因此我希望将以下函数定义为速记:
pack = fpack id
如果我将上面的程序加载到GHCi中并执行上面的行,那么pack将根据需要定义,并且它的类型(由:t
)是fpack(a->a)r=>r
。所以我在我的程序中这样定义了函数:
pack :: FPack (a -> a) r => r
pack = fpack id
但当将所述程序加载到GHCI中时,会出现以下错误:
bugs\so-pack.hs:31:8: error:
* Overlapping instances for FPack (a0 -> a0) r
arising from a use of `fpack'
Matching givens (or their superclasses):
FPack (a -> a) r
bound by the type signature for:
pack :: forall a r. FPack (a -> a) r => r
at bugs\so-pack.hs:30:1-29
Matching instances:
instance [overlappable] (f ~ (Nil -> r)) => FPack f r
-- Defined at bugs\so-pack.hs:24:31
instance (FPack (x -> b) r, f ~ (Cons a x -> b)) =>
FPack f (a -> r)
-- Defined at bugs\so-pack.hs:27:10
(The choice depends on the instantiation of `a0, r')
* In the expression: fpack id
In an equation for `pack': pack = fpack id
|
31 | pack = fpack id
|
这就引出了我的问题。为什么这个函数在GHCi中定义时起作用,而在程序中定义时却不起作用?有什么办法可以让这个程序正常运行吗?如果是,怎么做?
根据我对GHC和Haskell的理解,这个错误是因为pack
可以解析为两个重叠实例中的任何一个,这就困扰了GHC。但是,我认为allowAmbiguoustypes
选项应该通过将实例选择推迟到最终调用站点来解决这个问题。不幸的是,这显然是不够的。我很好奇为什么,但我更好奇的是为什么GHCi在它的REPL循环中接受这个定义,但当它在程序内部时却不接受它。
fpack id "a" "b" :: Cons [Char] (Cons [Char] Nil)
<interactive>:120:1: error:
* Couldn't match type `Cons [Char] (Cons [Char] Nil)' with `()'
arising from a use of `it'
* In the first argument of `System.IO.print', namely `it'
In a stmt of an interactive GHCi command: System.IO.print it
您需要手动实例化fpack
。
pack :: forall a r . FPack (a -> a) r => r
pack = fpack @(a->a) @r id
这需要ScopedTypeVariables,TypeApplications,AllowAmbiguousTypes
。
或者,提供id
的类型。
pack :: forall a r . FPack (a -> a) r => r
pack = fpack (id :: a -> a)
为什么我不能在Java中做到这一点: 不会是子类。add已经实现Context。add,因为它add(Object)可以执行add(Integer)可以执行的所有操作? 解决这个问题的好方法是什么? 现在我正在做一种丑陋的方式: 编辑:这不是上述问题的副本。在给定的问题中,超类是以更一般的“Object”作为参数的类,而子类则更具体。这不起作用,因为更具体的方法可能无法处理任何对象。在我的问题中,
问题内容: 在中,我们具有接口List和类: 并扩展AbstractList和 我的问题:为什么ArrayList有该implements List条款? 如果,我们不能说吗? 问题答案: 是。可以省略。但是,这是一个立即可见List。否则,将需要额外单击代码/文档。我认为这就是原因-清晰。 并补充的评论-这是为了展示该工具。总体而言,这只是为了方便起见,并减少了List实现之间的代码重复。
我认为它使用我的头作为一个背景,实际上并没有计算它作为头,因为某种原因,这是我的代码: 它与这三条线重叠:
谢谢你的帮助。Haskell看起来很有趣,但如果没有一个好教授的指导和指导,这是一门很难学的语言。我只是想自学这门语言。
问题内容: 这个问题已经在这里有了答案 : 为什么我不应该在PHP中使用mysql_ *函数? (15个答案) 6年前关闭。 不久前我停止使用这些功能时,在这里扮演了Devil’s Advocate的角色,但问题是真实的,可能对许多SO用户来说很重要。 我们都知道以错误的方式使用功能可能非常危险,可能使您的网站容易受到攻击等。但是正确使用这些功能可以防止SQL注入,并且实际上比新的PDO功能要快一
为了澄清我的问题,让我用一种或多或少相同的方式重新措辞: 为什么Haskell中有超类/类继承的概念?导致这种设计选择的历史原因是什么?例如,为什么有一个没有类层次结构的基库,只有相互独立的类型库是如此糟糕? 此外,我在类继承中看到的一个可能不太好的事情是:我认为一个类实例会默默地选择一个对应的超类实例,这可能是为该类型实现的最自然的实例。让我们把单子看作函子的子类。也许可以有不止一种方法来定义某