标签: haskell

GHC中自动专业化的传递性

来自GHC 7.6 的文档:

[Y]你通常甚至不需要SPECIALIZE pragma.在编译模块M时,GHC的优化器(带-O)自动考虑在M中声明的每个顶级重载函数,并将其专门用于在M中调用它的不同类型.优化器还考虑每个导入的INLINABLE重载函数,并将其专门用于M中调用的不同类型.

此外,给定函数f的SPECIALIZE编译指示,GHC将自动为f调用的任何类型类重载函数创建特殊化,如果它们与SPECIALIZE编译指示位于同一模块中,或者它们是INLINABLE; 等等,过渡性的.

因此GHC应该自动专门化一些INLINABLE 没有编译指示标记的/大多数/所有(?)函数,如果我使用显式编译指示,则特化是可传递的.我的问题是:auto -specialization 是否具有传递性?

具体来说,这是一个小例子:

Main.hs:

import Data.Vector.Unboxed as U
import Foo

main =
    let y = Bar $ Qux $ U.replicate 11221184 0 :: Foo (Qux Int)
        (Bar (Qux ans)) = iterate (plus y) y !! 100
    in putStr $ show $ foldl1' (*) ans
Run Code Online (Sandbox Code Playgroud)

Foo.hs:

module Foo (Qux(..), Foo(..), plus) where

import Data.Vector.Unboxed as U

newtype Qux r = Qux (Vector r)
-- …
Run Code Online (Sandbox Code Playgroud)

haskell ghc

391
推荐指数
1
解决办法
2万
查看次数

为什么我们需要monad?

我谦虚地看到着名问题"什么是单子?"的答案.,特别是投票最多的人,试着解释什么是monad而没有明确解释为什么monad真的是必要的.他们可以解释为问题的解决方案吗?

monads haskell

358
推荐指数
7
解决办法
5万
查看次数

什么是免费monad?

我见过的长期免费单子弹出每一个 现在 随后一段时间,但每个人似乎只是使用/讨论这些问题没有给予它们是什么解释.所以:什么是免费的monads?(我会说我熟悉monad和Haskell的基础知识,但对类别理论只有非常粗略的了解.)

monads haskell free-monad

357
推荐指数
7
解决办法
5万
查看次数

好的Haskell源码来阅读和学习

什么是一些使用Haskell的开源程序,可以被认为是优质的现代Haskell?代码库越大越好.

我想从他们的源代码中学习.我觉得我已经超越了从小代码示例中学到的东西,这些代码通常是深奥的,小世界的.我想看看代码是如何构造的,当你有很多事情发生时,monad如何交互(日志记录,I/O,配置等).

open-source haskell coding-style

343
推荐指数
7
解决办法
4万
查看次数

"编程代码"在编程环境中意味着什么?

我在函数式编程和PLT圈子中多次听到过"enggebras"这个术语,特别是在讨论对象,comonads,镜头等时.谷歌搜索这个术语给出了对这些结构进行数学描述的页面,这对我来说几乎是不可理解的.任何人都可以解释一下代数在编程环境中的意义,它们的意义是什么,以及它们与对象和共同体的关系?

haskell functional-programming scala category-theory recursion-schemes

334
推荐指数
4
解决办法
3万
查看次数

追踪约束的技巧

这是场景:我已经编写了一些带有类型签名的代码,并且GHC抱怨无法推断x~y某些xy.你通常可以将GHC作为一个骨骼并简单地将同构函数添加到函数约束中,但这有几个原因:

  1. 它并不强调理解代码.
  2. 你可以得到5个约束,其中一个就足够了(例如,如果5个被一个更具体的约束暗示)
  3. 如果你做错了什么或者GHC没有帮助,你最终可能会受到假的限制

我只花了几个小时与案例3作斗争.我正在玩syntactic-2.0,我试图定义一个与域无关的版本share,类似于在中定义的版本NanoFeldspar.hs.

我有这个:

{-# LANGUAGE GADTs, FlexibleContexts, TypeOperators #-}
import Data.Syntactic

-- Based on NanoFeldspar.hs
data Let a where
    Let :: Let (a :-> (a -> b) :-> Full b)

share :: (Let :<: sup,
          Domain a ~ sup,
          Domain b ~ sup,
          SyntacticN (a -> (a -> b) -> b) fi) 
      => a -> (a -> b) -> a
share = sugarSym Let
Run Code Online (Sandbox Code Playgroud)

和GHC could not …

haskell constraints ghc

321
推荐指数
1
解决办法
1万
查看次数

Haskell/GHC中的`forall`关键字有什么作用?

我开始理解forall关键字如何在所谓的"存在类型"中使用,如下所示:

data ShowBox = forall s. Show s => SB s
Run Code Online (Sandbox Code Playgroud)

然而,这仅仅是如何forall使用的一个子集,我根本无法将其用于这样的事情:

runST :: forall a. (forall s. ST s a) -> a
Run Code Online (Sandbox Code Playgroud)

或解释为什么这些是不同的:

foo :: (forall a. a -> a) -> (Char, Bool)
bar :: forall a. ((a -> a) -> (Char, Bool))
Run Code Online (Sandbox Code Playgroud)

或整个RankNTypes东西......

我倾向于选择清晰,无术语的英语而不是学术环境中常见的语言.我尝试阅读的大部分解释(我可以通过搜索引擎找到的解释)存在以下问题:

  1. 他们不完整.他们解释如何使用这个关键字(如"生存型")的一个组成部分这让我感到高兴,直到我读使用它在一个完全不同的方式代码(比如runST,foobar以上).
  2. 他们密集地充满了假设,我已经阅读了最新的离散数学分类,类别理论或抽象代数本周流行.(如果我再也没有读过"请参阅论文的任何细节",那就太早了.)
  3. 它们的编写方式经常将简单的概念转变为曲折的语法和语法.

所以...

关于实际问题.任何人都可以完全解释的forall清晰,简单的英语关键字(或者,如果它存在于某个地方,点到我已经错过了这样一个明确的解释),不承担我在行话悠久的数学家?


编辑添加:

下面有高质量的答案有两个突出的答案,但不幸的是我只能选择一个最好的答案. 诺曼的回答很详细的和有用的,解释的方式,表现出一定的理论基础的东西forall,并在同一时间向我展示了一些它的实际影响. yairchu的回答覆盖了其他人没有提到的范围(范围类型变量),并用代码和GHCi会话说明了所有概念.我愿意选择两者是最好的.不幸的是,我不能和上,俯瞰着两个答案后密切,我已经决定,yairchu的稍微挤掉了诺曼,因为说明性代码和附加的说明.这是一个有点不公平,但是,因为我真的需要这两个答案,了解这一点是一点forall没给我留下了恐惧的隐隐感觉,当我看到它在类型签名.

syntax haskell types ghc forall

295
推荐指数
7
解决办法
4万
查看次数

Haskell:什么是弱头正常形式?

什么是弱头范式(WHNF)是什么意思?什么是头标准型(HNF)和范式(NF)是什么意思?

真实世界Haskell说:

熟悉的seq函数将表达式计算为我们称之为head normal form(缩写为HNF)的表达式.它一旦到达最外面的构造函数("头部")就会停止.这与正常形式(NF)不同,其中表达式被完全评估.

您还将听到Haskell程序员引用弱头正常形式(WHNF).对于正常数据,弱头正常形式与头部正常形式相同.差异只出现在功能上,而且我们在这里无关紧要.

我已经阅读了一些资源和定义(Haskell WikiHaskell邮件列表自由词典),但我没有得到它.有人可能举一个例子或提供外行定义吗?

我猜它会类似于:

WHNF = thunk : thunk

HNF = 0 : thunk 

NF = 0 : 1 : 2 : 3 : []
Run Code Online (Sandbox Code Playgroud)

如何做seq($!)与WHNF和HNF有关?

更新

我还是很困惑.我知道有些答案会忽略HNF.通过阅读各种定义,似乎WHNF和HNF中的常规数据之间没有区别.但是,它似乎与功能有所区别.如果没有差异,为什么还seq需要foldl'

另一个混淆点来自Haskell Wiki,它指出seq减少到WHNF,并且对以下示例不做任何处理.然后他们说他们必须seq用来强迫评估.那不是强迫它到HNF吗?

常见的新手堆栈溢出代码:

myAverage = uncurry (/) . foldl' (\(acc, len) x -> (acc+x, len+1)) (0,0)
Run Code Online (Sandbox Code Playgroud)

了解seq和弱头正常形式(whnf)的人可以立即明白这里出了什么问题.(acc + x,len + 1)已经在whnf中,所以seq将值减少到whnf,对此无效.这段代码将像原始的foldl示例一样构建thunks,它们只是在元组内部.解决方案只是强制元组的组件,例如

myAverage …
Run Code Online (Sandbox Code Playgroud)

haskell definition strictness weak-head-normal-form

279
推荐指数
6
解决办法
3万
查看次数

滥用代数数据类型的代数 - 为什么这样做?

代数数据类型的"代数"表达式对于具有数学背景的人来说非常具有启发性.让我试着解释一下我的意思.

定义了基本类型

  • 产品
  • 联盟 +
  • 独生子 X
  • 单元 1

并使用简写X•X2XX+X等等,我们就可以定义如链表代数表达式

data List a = Nil | Cons a (List a)L = 1 + X • L

和二叉树:

data Tree a = Nil | Branch a (Tree a) (Tree a)T = 1 + X • T²

现在,我作为数学家的第一直觉是坚持这些表达方式,并试图解决LT.我可以通过重复替换来做到这一点,但似乎更容易滥用符号,并假装我可以随意重新排列.例如,对于链接列表:

L = 1 + X • L

(1 - X) • L = 1

L = 1 …

ocaml haskell functional-programming algebraic-data-types miranda

277
推荐指数
7
解决办法
1万
查看次数

推拉和箭头化玻璃钢的根本区别如何?

我想在Haskell中学习FRP,但要确定要使用的库有点困难.许多似乎是死亡的尝试,有些似乎已经复活(例如最近在Yampa的活动).

根据我的阅读,似乎FRP有两种"种类":一侧是推拉式FRP(如Reactive-banana),另一侧是箭头式FRP(如Yampa).似乎在弗兰和弗里斯时代曾经有过一些"经典的FRP",但我没有发现其中的任何近期活动.

  • 这两个(或三个)FRP真的是根本不同的方法吗?

  • 其中一个是过时的理论而另一个是"未来的东西"?

  • 或者它们是否必须并行发展,以满足不同的目的?

  • 我是否列出了每个类别中最突出的图书馆,还是有其他选择要考虑(Sodium,Netwire等)?


我终于在J. Abrahamson的评论中看到了Evan Czaplicki讲话.这非常有趣,并帮助我澄清了一些事情.我强烈推荐给发现这个问题的人.

haskell frp yampa reactive-banana

264
推荐指数
1
解决办法
1万
查看次数