我只是在注意学习阅读GHC Core时注意到,这是Eq枚举式数据类型的自动派生实例,如
data EType = ETypeA | ETypeB | ETypeC | ETypeD
           | ETypeE | ETypeF | ETypeG | ETypeH
           deriving (Eq)
在查看GHC的核心表示时,似乎会转换为类似O(N)的查找:
$fEqEType_$c== =
  \ (a_ahZ :: EType) (b_ai0 :: EType) ->
    case a_ahZ of _ {
      ETypeA ->
        case b_ai0 of _ {
          ETypeA -> True;
          ETypeB -> False;
          ETypeC -> False;
          ETypeD -> False;
          ETypeE -> False;
          ETypeF -> False;
          ETypeG -> False;
          ETypeH -> False
        };
      ETypeB -> case b_ai0 of _ …我最近在某处读过模式匹配在运行时发生而不是编译时.(我正在寻找源,但目前无法找到它.)这是真的吗?如果是这样,功能中的警卫是否具有相同的性能?
阅读这个对我来说是令人惊讶的,因为我曾经认为GHC能够在编译期间优化一些(可能不是全部)模式匹配决策.这会发生吗?
一个案例例如:
f 1 = 3
f 2 = 4
VS
f' a | a == 1 = 3
     | a == 2 = 4
执行f并f'编译为相同数量的指令(例如,在Core和/或更低版本中)?
如果我在构造函数上模式匹配而不是值,情况是否有所不同?例如,如果GHC发现始终使用一个构造函数调用某个位置的函数,它是否会以消除运行时检查的方式优化该调用?如果是这样,你能给我一个展示优化产生的例子的例子吗?
在性能方面有什么值得了解的这两种方法?
什么时候表现更好?
我正在通过学习你的haskell教程,我一直在嘲笑作者给出的一些例子.
例如,他重新实现zip如下:
zip' :: [a] -> [b] -> [(a,b)]  
zip' _ [] = []  
zip' [] _ = []  
zip' (x:xs) (y:ys) = (x,y):zip' xs ys
他对所有其他例子采用了类似的方法,他将最具体的模式放在第一位.这是一个略有不同的zip函数版本:
zip' :: [a] -> [b] -> [(a,b)]
zip' (x:xs) (y:ys)  = (x, y):zip' xs ys
zip' _ _            = []
据我所知,两种方法都做同样的事情.如果提供空列表(x:xs)或(y:ys)将不匹配,将通过附加空列表[]来完成递归.
亲切的问候,
编辑:
可能重复: Haskell GHC:模式与N个构造函数匹配的时间复杂度是多少?
简介:模式的顺序对于语义(在严格评估参数方面)和函数的可读性非常重要.模式匹配本身将始终处于O(1)时间复杂度.
我想知道如何在内部解决Haskell模式匹配以及它如何影响性能.假设我们有一个计算成本很高的函数,所以我们在进行实际计算之前预先计算第一个和/或更频繁使用的值和相应输入上的模式匹配:
expensiveComputation :: Int -> Int
expensiveComputation 1 = 101
expensiveComputation 2 = 3333333
expensiveComputation 3 = 42
...
expensiveComputation n = the actual function
如果我们想要的话,我们可以预先计算很多这些案例,但是我们呢?我假设Haskell实际上找到匹配输入的模式需要时间,所以也许它实际上更快计算第1000个值而不是1000个模式匹配?
我想在Haskell中硬编码地图.我至少可以看到三种方法:
使用多个方程式:
message 200 = "OK"
message 404 = "Not found"
...
使用case表达式:
message s = case s of
    200 -> "OK"
    404 -> "Not found"
实际上使用了Map.
这是最有效的方法吗?一种解决方案比其他解决方案更快,为什么?前两个解决方案是否相同?(编译器会生成相同的代码吗?)推荐的方法是什么(更容易阅读)?
(注意我Int在我的例子中使用,但这不是必需的.键也可能是Strings,所以我对这两种情况都很感兴趣.)
我正在读" 了解你一个Haskell",特别是有关模式匹配的章节.这是教程中提供的用于计算列表长度的代码:
length' :: (Num b) => [a] -> b  
length' [] = 0  
length' (_:xs) = 1 + length' xs
我的问题是,反转递归的顺序(通过放置基本情况下)显示任何显着的性能提升?
length' :: (Num b) => [a] -> b
length' (_:xs) = 1 + length' xs
length' [] = 0
我正在为我创建的数据类型编写一个"附加"函数(基本上处理"流").但是,这种数据类型有12种不同的构造函数,处理不同类型的"流",例如,无限,空,固定长度,可变长度,已经附加等.
输入类型和输出类型之间的逻辑有点复杂但并非如此令人难以置信.
我考虑过两种方法:
我知道第二种方法更难以维护,但忽视这一点,GHC会发现第二种方法更容易优化吗?如果它可以使用简单的跳转表(或者可能是两个跳转表)进行第二种方法,我怀疑它会更快.但是,如果它进行线性检查,它将会慢得多.
GHC是否将模式匹配(甚至非常大的匹配)优化为恒定时间跳转表?