Haskell 是否存在需要使用bottom才能获得正确类型的数据结构?
Haskell中是否存在绝对需要使用底部值的类型,即未定义的Haskell 是否存在需要使用bottom才能获得正确类型的数据结构?,haskell,types,Haskell,Types,Haskell中是否存在绝对需要使用底部值的类型,即未定义的?或者它只是用来在代码运行过程中编译代码 我认为可能存在一种罕见的类型,它需要undefined来完成它的构造,list只需要1:[]就可以了,但可能数据类型太复杂了,需要undefined`来完成它的构造 是否有更复杂的构造函数需要键入未定义的?有时,您只想传递一个值来传递该值的类型,而不关心实际值。例如asTypeOf::a->a->a。它不检查is seconds参数,它只是在那里设置类型a: Prelude> maxBou
?或者它只是用来在代码运行过程中编译代码
我认为可能存在一种罕见的类型,它需要undefined
来完成它的构造,list只需要1:[]
就可以了,但可能数据类型太复杂了,需要undefined`来完成它的构造
是否有更复杂的构造函数需要键入
未定义的?有时,您只想传递一个值来传递该值的类型,而不关心实际值。例如asTypeOf::a->a->a
。它不检查is seconds参数,它只是在那里设置类型a
:
Prelude> maxBound `asTypeOf` (0::Word)
18446744073709551615
Prelude> maxBound `asTypeOf` (0::Int)
9223372036854775807
Prelude> maxBound `asTypeOf` (undefined::Int)
9223372036854775807
如您所见,asTypeOf
在将undefined
作为其第二个参数的值传递时非常有效,因为任何Int
类型化的值都会导致maxBound
被视为Int
的maxBound
您可能会争辩说,将值传递给从不使用的asTypeOf
是一个愚蠢的想法。那种类型感觉不对。相反,您只需要传递一些包含类型信息的内容。虽然代理
的标准版本略有不同,但仍有使用该思想的代理
类型的实现。一个简单的代理
实现可以如下工作:
-- Note: No data constructor at all.
-- This type is uninhabitated, the only possible value is undefined
data Proxy a
-- generator function for a proxy value. As there is no value, it has to return
-- undefined.
proxy :: Proxy a
proxy = undefined
asProxiedBy :: a -> Proxy a -> a
asProxiedBy x _ = x
使用此代码,您可以编写
*Main> maxBound `asProxiedBy` (proxy :: Proxy Int)
9223372036854775807
在这个修订的示例中,将asTypeOf
替换为asProxiedBy
,您不再传递未使用的值,而是将未定义的值作为引用类型传递。为了避免拼写丑陋的单词undefined
,引入了proxy
方法来生成所有proxy
类型的undefined
值。最后我找到了一些适合undefined的示例:
newtype Wrap = W {w :: Wrap} deriving Show
www = W $ W $ W $ undefined
你可以数一数(没有尽头):
在这里,Wrap
需要undefined
结束
class Peano a where
zero :: a
next :: a -> a
alt_zero, alt_one, alt_two, alt_three :: (Peano a) => a
alt_zero = undefined
alt_one = next alt_zero -- = succ undefined
alt_two = next alt_one -- = succ (succ undefined)
alt_three = next alt_two -- = succ (succ (succ undefined))
在这里,您可以创建1、2、3而无需实例,也可以给出具体类型
data Nat = Z | S Nat deriving Show
instance (Peano Nat) where
zero = Z
next = S
instance (Peano Wrap) where
zero = undefined
next = W
countN :: Nat -> Int
countN Z = 0
countN (S n) = (countN n) + 1
以及一些实现。我知道如果我再多搜索一点,我会找到一些东西我还不确定我是否理解这个问题。你的问题是,是否有任何一种类型的任何一个具有该类型的术语是底部的?或者你是在问,是否有哪种类型的惯用用法涉及某个地方的底部?还是别的什么…?@DanielWagner非常感谢!有了你们的问题,我可以找到一些非常好的信息。看起来像一个例子。:)空树将为空=节点0未定义未定义
。(当然,你可以把任何东西放在那里,包括empty
或节点10000000 empty
;这不是一个好的设计。)是的,但你真的不应该使用那种代理,因为它让你使用未定义的!代理的通常定义是数据代理a=Proxy
。模式的全部要点是使用代理
——一个完全定义的值,而不是未定义的
,这样就可以完全避免需要未定义的
。在现代Haskell中,我相信几乎不需要asTypeOf
,如果有的话。由于ScopedTypeVariables
,编写x::T
现在总是可能的,而且它比x`asTypeOf`y
更好地记录了预期的类型,在这里您需要y
成为预期的类型。我们从不需要使用“`xasTypeOf
(undefined::T)”,因为这相当于x::T
,当我们不能显式地编写T
时,我们需要asTypeOf
,但我们手头有一个该类型的值,IIRC。或数据Void=Void!Void
,或者如果您不关心Haskell 98,数据Void
。但这些都很无聊。有更多有趣的使用底部在那里。看看我为Data.Sequence.zipWith
@dfeuer编写的定义,确实有!l=Seq$Deep 3(一个(元素(1,2)))EmptyT(两个未定义的元素(元素(5,6))Wrap
不需要undefined
结束:x=W x
不是底部(内部任何地方都不包含底部)。也许你想让它变成一个newtype
?@Daniel Wagner的确,你总是对的:)。这与“n=n+1”不一样吗?是的,W
是一个函数。但数据构造函数是特殊的:它们标记允许停止对WHNF的评估的位置。仅非构造函数应用程序不共享此属性。另见“保护递归”x=W x
受保护,而x=1+x
不受保护。
data Nat = Z | S Nat deriving Show
instance (Peano Nat) where
zero = Z
next = S
instance (Peano Wrap) where
zero = undefined
next = W
countN :: Nat -> Int
countN Z = 0
countN (S n) = (countN n) + 1