懒惰的数据结构评估

0xA*_*xAX 6 haskell lazy-evaluation

我正在读关于haskell的懒惰评估,并有一个问题.例如,我们有以下计算:

Prelude> let x = 1 + 1 :: Int
Prelude> let y = (x,x)
Run Code Online (Sandbox Code Playgroud)

获得价值之后x:

Prelude> :sprint x
x = _
Run Code Online (Sandbox Code Playgroud)

它没有评估.好的,现在让我们获得y的价值:

Prelude> :sprint y
y = (_,_)
Run Code Online (Sandbox Code Playgroud)

它也没有评估,因为y依赖x and it's unevaluated.现在让我们尝试相同的例子但没有::Int:

Prelude> let x = 1 + 1
Prelude> let y = (x, x)
Prelude> :sprint y
y = _
Run Code Online (Sandbox Code Playgroud)

为什么y_,而不是(_, _)当我们试图不::Int

我看到他们有不同的类型:

Prelude> let x = 1 + 1
Prelude> :t x
x :: Num a => a
Prelude> let x = 1 + 1 :: Int
Prelude> :t x
x :: Int
Run Code Online (Sandbox Code Playgroud)

但为什么价值y取决于它呢?

谢谢.

bhe*_*ilr 7

发生的事情是,当您指定x具有该类型时Num a => a,编译器不可能知道Num在执行时使用哪个实例1 + 1.它的作用是使用默认.GHC定义了某些类型类的默认类型,这样当没有可能的方法来确定使用哪种具体类型时,它仍然可以提供有意义的结果而不会引发错误.所以当你看到

> let x :: Num a => a
|     x = 1 + 1
> x
2
> :sprint x
x = _
Run Code Online (Sandbox Code Playgroud)

这是因为GHCI选择Integer作为其默认类型Num,但是当它执行此操作不结果存储在x的存储位置,因为没有办法知道,如果这是即使正确答案.这就是为什么你看到x = _:sprint,它实际上并没有进行评估x :: Num a => a,它的评估x :: Integer.你甚至可以自己搞乱这个默认值:

> newtype MyInt = MyInt Int deriving (Eq)
>
> instance Show MyInt where
|     show (MyInt i) = show i
> instance Num MyInt where
|     (MyInt x) + (MyInt y) = MyInt (x - y)
|     fromInteger = MyInt . fromInteger
>
> default (MyInt)
> x
0
Run Code Online (Sandbox Code Playgroud)

所以现在我们已经说过了1 + 1 = 0!请记住,您可能永远不会使用GHC的这个功能,但它是很好的了解.