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取决于它呢?
谢谢.
发生的事情是,当您指定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的这个功能,但它是很好的了解.