简体   繁体   English

故意在haskell中定义无限类型

[英]Deliberately defining infinite type in haskell

I want to define what seems to require an infinite type. 我想定义似乎需要无限类型的东西。

Required : a function "eat" that eats all it's arguments except "3" for which it returns 3 必需:一个函数“吃”吃掉它除了“3”之外的所有参数,它返回3

eat 3 = 3
eat x = eat

So basically an arbitrary expression like "eat (+) foldl (Just 5) 3" evaluates to 3. But the problem here is the type of eat. 所以基本上像“吃(+)foldl(Just 5)3”这样的任意表达式评估为3.但这里的问题是吃的类型。 What should that be? 应该是什么?

The closest i got to a running code was : 我得到的最接近的运行代码是:

newtype Rec = MakeRec (Int -> Rec)

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


instance Show Rec where
     show _ = "EAT"

This works okay for "eat 6" but not for "eat 6 7" and it doesn't work if i put (eat 3 = 3) in it's definition. 这适用于“吃6”而不是“吃6 7”,如果我把(吃3 = 3)放在它的定义中它就不起作用。

I am not sure if this is even possible in Haskell. 我不确定这在Haskell中是否可行。 (What argument would one use to show it's not possible ?) (用什么论证来表明它是不可能的?)

UPDATE : As noted in solution below, the type-information is needed at compile time so that compiler can know if "eat foldl 3 foldl" is invalid or not. 更新:如下面的解决方案中所述,在编译时需要类型信息,以便编译器可以知道“eat foldl 3 foldl”是否无效。 So, exact solution to this problem is not possible. 因此,这个问题的确切解决方案是不可能的。

It's not possible. 这是不可能的。 Infinite types (that aren't data types) are explicitly forbidden in Haskell, and it's easy to produce code which would require them, and thus produces an error (for example, try let foo = (42, foo) in foo ). 在Haskell中显式禁止无限类型(不是数据类型),并且很容易生成需要它们的代码,从而产生错误(例如, let foo = (42, foo) in foo尝试let foo = (42, foo) in foo )。

You can, of course, create them with newtype and data , like you did, but then you have to explicitly wrap and unwrap the values in and out of constructors. 当然,您可以使用newtypedata创建它们,就像您一样,但是您必须明确地将值包装并拆分为构造函数。

This is an explicit design decision: with infinite types, many obviously wrong expressions that we would like the compiler to reject would have to be allowed, and since many more programs would be allowed, a lot of previously unambiguously-typed programs would become ambiguously typed, 1 requiring explicit type annotations. 这是一个明确的设计决策:对于无限类型,我们希望编译器拒绝的许多明显错误的表达式必须被允许,并且由于允许更多的程序,许多以前明确类型的程序将变得模糊地键入, 1需要显式类型注释。 So a tradeoff is made: requiring you to be explicit about the fairly rare uses of infinite types in return for getting much more help from the type system than we otherwise would. 因此需要进行权衡:要求您明确表示无限类型的相当罕见的用途,以换取从类型系统获得比我们原本更多的帮助。

That said, there is a way to define something similar to your eat function, using typeclasses, but it can't stop only when you give it a 3: whether you've given it a 3 or not can only be determined at runtime, and types are decided at compile time. 这就是说,有一种方法可以定义类似的东西eat功能,使用类型类,但是当你给它不仅可以停止3:你是否已经给它一个3与否只能在运行时确定的,和类型在编译时决定。 However, here's an overloaded value that can be both an Integer , and a function that just eats up its argument: 但是,这是一个重载值,既可以是Integer ,也可以是只占用其参数的函数:

class Eat a where
    eat :: a

instance Eat Integer where
    eat = 3

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

The catch is that you need to specify the types precisely when you use it: 问题是您需要在使用时精确指定类型:

*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

This is because eat 1 foldr () could be an Integer , but it could also be another function, just as we used eat 1 and eat 1 foldr as functions in the same expression. 这是因为eat 1 foldr ()可能是一个Integer ,但也可能是另一个函数,正如我们在同一个表达式中使用eat 1eat 1 foldr函数一样。 Again, we get flexible typing, but have to explicitly specify the types we want in return. 同样,我们得到灵活的输入,但必须明确指定我们想要的类型。

1 Think typeclass overloading, like the overloaded numeric literals ( 42 can be any type that's an instance of Num ). 1想想类型类重载,比如重载的数字文字( 42可以是任何类型的Num实例)。

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

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