小编Gab*_*lez的帖子

代数解释多态性

所以我理解类型的基本代数解释:

Either a b ~ a + b
(a, b) ~ a * b
a -> b ~ b^a
()   ~ 1
Void ~ 0 -- from Data.Void
Run Code Online (Sandbox Code Playgroud)

......并且这些关系对于具体类型是正确的,例如Bool,与多态类型相反a.我还知道如何通过根据以下同构转换Church编码,将具有多态类型的类型签名转换为具体类型表示:

(forall r . (a -> r) -> r) ~ a
Run Code Online (Sandbox Code Playgroud)

所以,如果我有:

id :: forall a . a -> a
Run Code Online (Sandbox Code Playgroud)

我知道这并不意味着id ~ a^a,但它实际上意味着:

id :: forall a . (() -> a) -> a
id ~ ()
   ~ 1
Run Code Online (Sandbox Code Playgroud)

同理:

pair :: forall r . (a -> …
Run Code Online (Sandbox Code Playgroud)

haskell types

53
推荐指数
3
解决办法
3094
查看次数

是否有一个无符号整数类型会警告负面文字?

ghc如果整数文字超出给定类型的范围,则最新版本将警告您.例如:

$ ghci
>>> let x = 330492039485 :: Data.Word.Word8
<interactive>:2:9: Warning:
    Literal 330492039485 is out of the GHC.Word.Word8 range 0..255
Run Code Online (Sandbox Code Playgroud)

但是,ghc不会警告Data.Word类型的负数字文字.相反,它下溢(故意,根据文档):

>>> let x = -1 :: Data.Word.Word8
>>> x
255
Run Code Online (Sandbox Code Playgroud)

是否有任何类型会警告负面文字或有没有办法我可以创建自己的自定义类型,它会发出警告?

haskell ghc

25
推荐指数
1
解决办法
1102
查看次数

使用INLINABLE编译指示的缺点

我正在问这个问题,希望能够完善Simon Marlow先前给出的一个问题的答案INLINABLE,链接在这里:

是否有任何理由不使用INLINABLE pragma作为函数?

我意识到这几乎是这个问题的重复,除了Simon Marlow没有回答对许多图书馆作者来说最重要的关键问题:从纯粹的性能角度来看,将INLINABLEpragma 添加到所有内容是否安全?

据我所知,唯一的缺点是:

  • 编译时间较慢

  • 更大的接口文件(即*.hi)

但我真正想知道的是,由于添加了INLINABLEpragma,代码是否会运行得更慢?换句话说,一个INLINABLEpragma是否会导致GHC选择一个不太理想的优化?

我问的原因是,包括我自己在内的许多库作者并不关心接口文件的大小,并且在添加INLINABLE编译指示时我们没有观察到编译的显着减慢,所以很容易在任何地方反复添加它们,因为那里这样做似乎没有代价.

相反,将它们ghc遗漏的成本是,当模块变得非常大时,开始选择性地从接口文件中省略一些函数以节省空间,这有时会导致更差的优化,并且很难预测这将发生在什么时候和它将省略哪些功能.

我个人从来没有目睹过由于INLINABLE注释而运行速度较慢的函数,但这可能完全归功于运气.如果有些情况INLINABLE会使事情变慢,我想知道为什么会这样做,以便我可以更好地推断何时添加编译指示而不是繁琐地对编译器编译指示的每个排列进行基准测试.

optimization haskell ghc

24
推荐指数
1
解决办法
708
查看次数

重新绑定索引monad的表示法

我正在关注Conor McBride的"Kleisli箭头的令人发指的财富"论文,我在这里发布了我的代码实现.简而言之,他定义了以下类型和类:

type a :-> b = forall i . a i -> b i

class IFunctor f where imap :: (a :-> b) -> (f a :-> f b)

class (IFunctor m) => IMonad m where
    skip :: a :-> m a
    bind :: (a :-> m b) -> (m a :-> m b)

data (a := i) j where
    V :: a -> (a := i) i
Run Code Online (Sandbox Code Playgroud)

然后他定义了两种类型的绑定,后者(:=)用于限制初始索引:

-- Conor McBride's "demonic bind"
(?>=) …
Run Code Online (Sandbox Code Playgroud)

haskell

21
推荐指数
1
解决办法
1018
查看次数

如何在Haskell中进行快速数据反序列化

基准测试表明,对于cereal我的数据结构(详见下文),反序列化所需的时间比从驱动器读取相同数据所需的时间长100倍:

benchmarking Read
mean: 465.7050 us, lb 460.9873 us, ub 471.0938 us, ci 0.950
std dev: 25.79706 us, lb 22.19820 us, ub 30.81870 us, ci 0.950
found 4 outliers among 100 samples (4.0%)
  4 (4.0%) high mild
variance introduced by outliers: 53.460%
variance is severely inflated by outliers

benchmarking Read + Decode
collecting 100 samples, 1 iterations each, in estimated 6.356502 s
mean: 68.85135 ms, lb 67.65992 ms, ub 70.05832 ms, ci 0.950
std dev: 6.134430 ms, lb …
Run Code Online (Sandbox Code Playgroud)

performance serialization haskell

20
推荐指数
1
解决办法
2042
查看次数

内联派生类型类方法

Haskell允许您派生类型类实例,例如:

{-# LANGUAGE DeriveFunctor #-}

data Foo a = MakeFoo a a deriving (Functor)
Run Code Online (Sandbox Code Playgroud)

...但有时基准测试表明,如果您手动实现类型类实例并使用以下方法注释类型类方法,性能会提高INLINE:

data Foo a = MakeFoo a a

instance Functor Foo where
    fmap f (MakeFoo x y) = MakeFoo (f x) (f y)
    {-# INLINE fmap #-}
Run Code Online (Sandbox Code Playgroud)

有没有办法让两全其美?换句话说,有没有办法派生类型类实例,并使用INLINE?注释派生的类型类方法?

haskell

20
推荐指数
1
解决办法
267
查看次数

隐含提升的正确性

想象一下,我有一个比monad更通用的值:

m :: (Monad m) => m A  -- 'A' is some concrete type
Run Code Online (Sandbox Code Playgroud)

现在让我们说我将这个值专门化为一个具体的monad变换器堆栈,有两种不同的方式:

m1 :: T M A
m1 = m

m2 :: T M A
m2 = lift m
Run Code Online (Sandbox Code Playgroud)

...在哪里MT M是monad,并且T是monad变换器:

instance Monad M where ...
instance (Monad m) => Monad (T m) where ...
instance MonadTrans T where ...
Run Code Online (Sandbox Code Playgroud)

......这些实例遵守monad法律和monad变压器法则.

我们可以推断出:

m1 = m2
Run Code Online (Sandbox Code Playgroud)

...... m除了它的类型之外什么都不知道?

这只是一个冗长的方式,询问是否lift m是一个有效的替代m,假设两种类型检查.这个问题有点难以理解,因为它需要m在替换之前和之后将类型检查作为两个单独的monad.据我所知,这种替换进行类型检查的唯一方法m是在monad上是否通用.

我模糊的直觉是替换应该总是正确的,但我不确定我的直觉是否正确,或者如果它是正确的,如何证明它.

haskell types

9
推荐指数
1
解决办法
441
查看次数

GHC的-O和-O2之间的差异

cabal dist阻止你使用,-O2因为它产生更长的编译时间,GHC手册说:

目前,-O2不太可能产生比代码更好的代码-O.

我知道我总是可以对库进行基准测试,看看是否能-O2提供更好的性能,但我想知道是否有人可以解释有什么-O2不同,-O所以我可以直截了当地说他们认为不太可能产生更好的代码.

compiler-construction optimization haskell ghc

8
推荐指数
1
解决办法
592
查看次数

递归类型系列

我正在尝试一个mtl允许我Pipe在外部monad 上提升构图的类式.为此,我必须定义该类型的哪两个变量是Pipe组合的域和codomain .

我尝试使用相关的类型系列方法,但无济于事:

{-# LANGUAGE TypeFamilies #-}

import Control.Monad.Trans.Free
import Control.Monad.Trans.State
import Control.Pipe hiding (Pipe)

data Pipe a b m r = Pipe { unPipe :: FreeT (PipeF a b) m r }

class MonadPipe m where
    type C a b (m :: * -> *) :: * -> *
    idT :: C a a m r
    (<-<) :: C b c m r -> C a b m r -> C a …
Run Code Online (Sandbox Code Playgroud)

haskell type-families

7
推荐指数
2
解决办法
707
查看次数

多态约束

我有一些做作的类型:

{-# LANGUAGE DeriveFunctor #-}

data T a = T a deriving (Functor)
Run Code Online (Sandbox Code Playgroud)

......那个类型是一些人为的类的实例:

class C t where
    toInt :: t -> Int

instance C (T a) where
    toInt _ = 0
Run Code Online (Sandbox Code Playgroud)

如何在一个函数约束中表达,它T a是一个所有类的实例a

例如,请考虑以下功能:

f t = toInt $ fmap Left t
Run Code Online (Sandbox Code Playgroud)

直觉上,我希望,因为上面的功能工作toInt的作品T a为所有a,但我无法表达的类型.这不起作用:

f :: (Functor t, C (t a)) => t a -> Int
Run Code Online (Sandbox Code Playgroud)

...因为当我们应用fmap类型已成为Either a b.我无法解决这个问题:

f :: (Functor t, C (t …
Run Code Online (Sandbox Code Playgroud)

haskell types

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