【问题标题】:Haskell type `forall a . (Num a, Integral a) => a` for an integer constant of many typesHaskell 类型`forall a . (Num a, Integral a) => a` 用于多种类型的整数常量
【发布时间】:2014-07-21 11:06:39
【问题描述】:

在 Haskell 中编写 FFI 代码时,我经常将 IntCInt 变量混合在一起。我尝试定义一个新类型Intlike 来帮助定义可以表示为任一类型值的常量,如下所示:

type Intlike = forall a . (Num a, Integral a) => a
floatSize :: Intlike = fromIntegral $ sizeOf (1 :: CFloat)

然后GHCi这样抱怨:

Fractal.hs:276:24-35: No instance for (Num Intlike) arising from \
                                         a use of ‘fromIntegral’ …
    In the expression: fromIntegral
    In the expression: fromIntegral $ sizeOf (1 :: CFloat)
    In a pattern binding:
      floatSize :: Intlike = fromIntegral $ sizeOf (1 :: CFloat)
Compilation failed.

(这是Rank2Types 语言扩展。)

但是,以下方法有效:

floatSize :: (Num a, Integral a) => a
floatSize = fromIntegral $ sizeOf (1 :: CFloat)

有没有让我一直写fromIntegral 的好解决方案? Intlike 和有效的有什么区别?它们看起来很相似。

【问题讨论】:

    标签: haskell


    【解决方案1】:

    我不能告诉你为什么,但如果你写

    floatSize :: Intlike
    floatSize = fromIntegral $ sizeOf (1 :: CFloat)
    

    然后它工作得很好。一种可能性是模式变量上的类型注释正在做一些你所期望的事情(我从来没有真正理解过那些做什么)。请注意,您的Num 上下文是多余的,因为IntegralNum 的子类。至于fromIntegral,几乎任何时候你都需要在整数类型之间切换。另一种选择是使用“通用”函数来满足您的需求。例如,您可以定义

    import Foreign.Storable (sizeOf, Storable)
    
    genericSizeOf :: (Storable a, Integral b) => a -> b
    genericSizeOf = fromIntegral . sizeOf
    

    旁注:当使用像sizeOf 这样的函数只接受其类型的参数时,我个人更喜欢使用undefined 而不是任意值。所以我会写sizeOf (undefined::CInt)而不是sizeof (1::CInt)。这清楚地表明我传递的值无关紧要,并减少了“这是什么 1?如果我将其更改为 2 会发生什么?”的心理混乱


    在下面的 cmets 中,Boyd Stephen Smith, Jr. 提到了另一种显然是首选的方法,尽管我还没有阅读过它。

    【讨论】:

    • 你是对的!我没有注意到这一点。显式扩展类型也可以:floatSize :: (forall ...) = ....
    • 关于fromIntegral:我每CInt(或CSize)得到一个Int乘法,并不是那么少。
    • @Kirill,我扩展了我的答案以展示如何减少 fromIntegrals。
    • 对于只接受其类型的参数的函数,它们应该使用类型签名p a -> b 并使用值Proxy :: Proxy a(如果是迂腐的)或[] :: [a](如果是晦涩)。
    • @Kirill stackoverflow.com/a/22116440/2008899stackoverflow.com/a/13629758/2008899(在 cmets 中)加上 hackage.haskell.org/package/tagged-0.7.2/docs/Data-Tagged.html 提到它不仅更安全,而且优化得更好。
    猜你喜欢
    • 1970-01-01
    • 2011-04-14
    • 1970-01-01
    • 2020-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-25
    相关资源
    最近更新 更多