繁体   English   中英

故意在haskell中定义无限类型

[英]Deliberately defining infinite type in haskell

我想定义似乎需要无限类型的东西。

必需:一个函数“吃”吃掉它除了“3”之外的所有参数,它返回3

eat 3 = 3
eat x = eat

所以基本上像“吃(+)foldl(Just 5)3”这样的任意表达式评估为3.但这里的问题是吃的类型。 应该是什么?

我得到的最接近的运行代码是:

newtype Rec = MakeRec (Int -> Rec)

eat :: Int -> Rec
eat x = MakeRec eat


instance Show Rec where
     show _ = "EAT"

这适用于“吃6”而不是“吃6 7”,如果我把(吃3 = 3)放在它的定义中它就不起作用。

我不确定这在Haskell中是否可行。 (用什么论证来表明它是不可能的?)

更新:如下面的解决方案中所述,在编译时需要类型信息,以便编译器可以知道“eat foldl 3 foldl”是否无效。 因此,这个问题的确切解决方案是不可能的。

这是不可能的。 在Haskell中显式禁止无限类型(不是数据类型),并且很容易生成需要它们的代码,从而产生错误(例如, let foo = (42, foo) in foo尝试let foo = (42, foo) in foo )。

当然,您可以使用newtypedata创建它们,就像您一样,但是您必须明确地将值包装并拆分为构造函数。

这是一个明确的设计决策:对于无限类型,我们希望编译器拒绝的许多明显错误的表达式必须被允许,并且由于允许更多的程序,许多以前明确类型的程序将变得模糊地键入, 1需要显式类型注释。 因此需要进行权衡:要求您明确表示无限类型的相当罕见的用途,以换取从类型系统获得比我们原本更多的帮助。

这就是说,有一种方法可以定义类似的东西eat功能,使用类型类,但是当你给它不仅可以停止3:你是否已经给它一个3与否只能在运行时确定的,和类型在编译时决定。 但是,这是一个重载值,既可以是Integer ,也可以是只占用其参数的函数:

class Eat a where
    eat :: a

instance Eat Integer where
    eat = 3

instance (Eat r) => Eat (a -> r) where
    eat _ = eat

问题是您需要在使用时精确指定类型:

*Main> eat 1 foldr ()

<interactive>:6:1:
    Ambiguous type variable `t0' in the constraint:
      (Eat t0) arising from a use of `eat'
    Probable fix: add a type signature that fixes these type variable(s)
    In the expression: eat 1 foldr ()
    In an equation for `it': it = eat 1 foldr ()
*Main> eat 1 foldr () :: Integer
3

这是因为eat 1 foldr ()可能是一个Integer ,但也可能是另一个函数,正如我们在同一个表达式中使用eat 1eat 1 foldr函数一样。 同样,我们得到灵活的输入,但必须明确指定我们想要的类型。

1想想类型类重载,比如重载的数字文字( 42可以是任何类型的Num实例)。

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM