小编cro*_*eea的帖子

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万
查看次数

追踪约束的技巧

这是场景:我已经编写了一些带有类型签名的代码,并且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万
查看次数

什么时候-XAllowAmbiguousTypes合适?

我最近发布了一个问题,关于句法2.0有关的定义share.我在GHC 7.6中有这个工作:

{-# LANGUAGE GADTs, TypeOperators, FlexibleContexts #-}

import Data.Syntactic
import Data.Syntactic.Sugar.BindingT

data Let a where
    Let :: Let (a :-> (a -> b) :-> Full b)

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

但是,GHC 7.8希望-XAllowAmbiguousTypes …

haskell ghc

212
推荐指数
1
解决办法
6070
查看次数

约束专业化

我遇到了让GHC专门化一个具有类约束的函数的问题.我有我的问题就在这里的一个小例子:Foo.hsMain.hs.这两个文件编译(GHC 7.6.2,ghc -O3 Main)并运行.

注意: Foo.hs真的被剥离了.如果您想了解为什么需要约束,可以在这里看到更多代码.如果我将代码放在一个文件中或进行许多其他微小的更改,GHC只是简单地将调用内联到plusFastCyc.这不会发生在实际代码中,因为plusFastCycGHC内联太大,即使在标记时也是如此INLINE.关键是要专门调用plusFastCyc,而不是内联它.plusFastCyc在真实代码的许多地方被调用,所以即使我可以强迫GHC这样做,也不可能复制这么大的功能.

感兴趣的代码是plusFastCycin Foo.hs,在这里转载:

{-# INLINEABLE plusFastCyc #-}
{-# SPECIALIZE plusFastCyc :: 
         forall m . (Factored m Int) => 
              (FastCyc (VT U.Vector m) Int) -> 
                   (FastCyc (VT U.Vector m) Int) -> 
                        (FastCyc (VT U.Vector m) Int) #-}

-- Although the next specialization makes `fcTest` fast,
-- it isn't useful to me in …
Run Code Online (Sandbox Code Playgroud)

haskell ghc

155
推荐指数
1
解决办法
5993
查看次数

GHC-7.6中的数据构造函数升级

我有这个代码:

class SymbolSet tpe where
  data Symbol tpe :: *

data SSet tpe where
  Identity :: tpe -> SSet tpe
  And :: SSet tpe -> Symbol tpe -> SSet tpe

class HasElem a b where

instance (SymbolSet tpe) => HasElem (And (Identity tpe) s) s
instance (HasElem sset s) => HasElem (And sset s) s
Run Code Online (Sandbox Code Playgroud)

这是在GHC-7.4中编译的.但是,在转向GHC-7.6时,它开始出现编译错误:

'And' of tpe `forall tpe. tpe -> Symbol * tpe -> SSet tpe' is not promotable
Run Code Online (Sandbox Code Playgroud)

在挖掘文档时,我发现在GHC-7.6GHC-7.4的 "数据类型升级"页面中添加了一个新的条款

我们不会提升其构造函数是多态的,涉及约束或使用存在量化的数据类型.

我的问题是:

  1. 不推广此类构造函数背后的理由是什么? …

constructor haskell ghc

63
推荐指数
1
解决办法
1583
查看次数

如何设计monadic堆栈?

你如何设计和构建你的monadic堆栈?我第一次需要构建一个monadic堆栈(使用变换器)来解决现实问题,但我并不完全确定堆叠变换器的顺序.如你所知,只要计算有点* -> *,基本上任何东西都可以在变换器中扮演内部monad的角色,因此有几个问题:

  • 一些特定的变压器应该在堆栈的顶部(例如ReaderT?WriterT?)
  • 什么应该驱动设计?直觉?类型?(例如根据API的需要塑造堆栈)
  • 每个堆栈是否彼此同形(在某种程度上)或者可能是,如果我错误地构建我的堆栈,我可能最终无法使用某些底层monad或者有一个大臃肿的混乱lift . lift . liftIO [...]?我的直觉是,如果变形金刚得到一些实例(例如MonadReader,MonadIO等,就像大多数变形金刚mtl一样),那么放置变压器的顺序并不重要.

我有兴趣听取经验丰富的Haskellers关于最佳实践或经验法则的意见.

forever $ print "Thanks!"

一个.

haskell types design-patterns monad-transformers

22
推荐指数
2
解决办法
834
查看次数

HOAS的复制机翻译

在关于DSL的无标记最终解释器的这些非常酷的注释的第2.3节中,Oleg Kiselyov展示了如何解决一次解析序列化DSL表达式并多次解释它的问题.

简而言之,他用类型表明了"伪造的一流多态"

newtype Wrapped = Wrapped (? repr. ExpSYM repr ? repr)
fromTree :: String ? Either ErrMsg Wrapped
Run Code Online (Sandbox Code Playgroud)

不令人满意,因为它是不可扩展的:我们必须有不同的Wrapper/ fromTree为每个上的约束repr.因此,我倾向于使用他的复制器解释器的解决方案.这个问题是关于如何使用HOAS的解释器.

具体来说,请考虑以下语言进行目标语言绑定:

class Lam repr where
  lam :: (repr a -> repr b) -> repr (a -> b)
  app :: repr (a -> b) -> repr a -> repr b
Run Code Online (Sandbox Code Playgroud)

我在为复制器解释器提供类的声音实例时遇到了麻烦Lam.这就是我所拥有的:

data Dup repr1 repr2 a = Dup {unDupA :: …
Run Code Online (Sandbox Code Playgroud)

dsl haskell ghc

19
推荐指数
1
解决办法
304
查看次数

〜的优先级是什么,为什么?

以下代码段编译:

{-# LANGUAGE TypeFamilies #-}
type family Foo a b

f :: (Foo a b ~ Int) => a -> b -> b
f = error ""
Run Code Online (Sandbox Code Playgroud)

但是中类型操作符似乎表现不同:

{-# LANGUAGE TypeFamilies #-}
type family a \\ b

f :: (a \\ b ~ Int) => a -> b -> b
f = error ""
Run Code Online (Sandbox Code Playgroud)

GHC抱怨第二个论点\\应该是善意的*,但是b ~ Int有点善意Constraint.当然这可以用parens修复,但我想知道是否还有另一种方法.

我试过设置我的运营商与固定性声明的优先级infixl 9 \\,但这并不解决问题,这表明的优先级~至少9(如果我解释是正确的).我尝试使用这个答案中的技巧让GHCi告诉我优先级~,但它没有用. …

haskell

18
推荐指数
1
解决办法
323
查看次数

一种避免常见使用unsafePerformIO的方法

我经常在Haskell代码中找到这种模式:

options :: MVar OptionRecord
options = unsafePerformIO $ newEmptyMVar

...

doSomething :: Foo -> Bar
doSomething = unsafePerformIO $ do
  opt <- readMVar options
  doSomething' where ...
Run Code Online (Sandbox Code Playgroud)

基本上,一个人有一个选项或类似的记录,最初是在程序开始时设置的.由于程序员很懒惰,他不想options在整个程序中携带记录.他定义了一个MVar保持它 - 由丑陋的使用定义unsafePerformIO.程序员确保状态只设置一次,并且在任何操作发生之前.现在程序的每个部分都必须unsafePerformIO再次使用,只是为了提取选项.

在我看来,这样的变量被认为是实用的纯粹(不要打败我).是否有一个库抽象出这个概念,并确保变量只设置一次,即在初始化之前没有调用,并且不需要写unsafeFireZeMissilesAndMakeYourCodeUglyAnd DisgustingBecauseOfThisLongFunctionName

haskell global-variables purely-functional unsafe-perform-io

16
推荐指数
3
解决办法
2375
查看次数

Haskell反思中的黑魔法

我希望有人可以对Data.Reflection中的黑魔法有所了解.相关片段是:

{-# LANGUAGE CPP #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE KindSignatures #-}

module Data.Reflection
    (
      Reifies(..)
    , reify
    ) where

import Data.Proxy
import Unsafe.Coerce

class Reifies s a | s -> a where
  -- | Recover a value inside a 'reify' context, given a proxy for its
  -- reified type.
  reflect :: proxy s -> a

newtype Magic a r = Magic (forall …
Run Code Online (Sandbox Code Playgroud)

reflection haskell

16
推荐指数
1
解决办法
2536
查看次数