gpt4 book ai didi

haskell - Haskell 中的求值、let 和 where

转载 作者:行者123 更新时间:2023-12-02 12:18:51 24 4
gpt4 key购买 nike

我目前正在学习 Haskell,并试图了解如何评估类型类,以及 letwhere 如何工作。此代码运行良好:

{-# LANGUAGE FlexibleInstances #-}
class Expr a where
literal :: Integer -> a

instance Expr Integer where
literal = id

instance Expr [Integer] where
literal i = [i]

coerceInteger :: Integer -> Integer
coerceInteger = id

main = print $ coerceInteger (literal 100) : literal 100 -- Prints [100,100]

但将 main 函数更改为

main = print $ coerceInteger expr : expr
where expr = literal 200

导致编译器错误:

Couldn't match expected type `[Integer]' with actual type `Integer'
In the second argument of `(:)', namely `expr'
In the second argument of `($)', namely `coerceInteger expr : expr'
In the expression: print $ coerceInteger expr : expr

我猜测这是因为在第一个 main 方法中,literal 100 被计算了两次,而在第二个示例中 literal 200仅评估一次,因此编译器被迫选择一种类型。

如何提取该代码以避免重复自己,而不导致此错误?我尝试使用 let expr =literal 300 in ... 但遇到了同样的问题。

最佳答案

问题是literal 200在第一个示例的两种不同上下文中,其解释有所不同。将其视为

((:) :: a -> [a] -> [a])
((coerceInteger :: Integer -> Integer) (literal 100 :: Expr a => a))
(literal 100 :: Expr a => a)

仅根据类型,编译器就确定第一个 literal 100必须有类型 Integer因为它被传递到 coerceInteger ,因为它必须采用 Integer 类型的值。这也设置了 (:) 的类型到现在是Integer -> [Integer] -> [Integer] ,意味着最后一个literal 100必须有类型 [Integer] .

在第二个示例中,您说它们具有相同的值,因此具有相同的类型,这是不可能的,因为第二个必须是 (:) 的列表。键入检查。

这实际上是由于可怕的单态限制而发生的。您可以通过两种方式解决此问题:一,使用 {-# LANGUAGE NoMonomorphismRestriction #-} 关闭单态限制。 ,或者您可以向 expr 提供显式类型这使其保持通用性:

main :: IO ()
main = print $ coerceInteger expr : expr
where
expr :: Expr a => a
expr = literal 100

这两种方法都有效,无论您决定做什么,我都建议始终提供类型签名来帮助避免这些问题。

<小时/>

事实上,一旦添加类型签名,您甚至可以执行类似的操作

main :: IO ()
main = print $ coerceInteger expr : expr : expr : expr : expr : expr
where
expr :: Expr a => a
expr = literal 100

如果没有任何问题,这将打印出 [100, 100, 100, 100, 100, 100] 。初始coerceInteger不过,这是需要的,因为否则编译器将不知道将其实例化为什么,因此不会有 Show print 的实例.

关于haskell - Haskell 中的求值、let 和 where,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24748388/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com