【问题标题】:Using newtype in Data.Array.Unboxed with ghc 7.10在 ghc 7.10 中使用 Data.Array.Unboxed 中的 newtype
【发布时间】:2017-04-19 15:18:30
【问题描述】:

这在 ghc 7.8.4 中运行良好,但在 7.10.3 中失败:

{-# LANGUAGE DeriveGeneric              #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module Foo where

import qualified Data.Array.Unboxed       as A
import           GHC.Generics             (Generic)

newtype Elt = Elt Int deriving (Eq, Ord, Show, Num, Integral, Real, Enum, A.IArray A.UArray, Generic)
type MyArr = A.UArray Int Elt

有很多类似的消息

/tmp/my.hs:9:75:
    Couldn't match type ‘Int’ with ‘Elt’
    arising from the coercion of the method ‘Data.Array.Base.numElements’
      from type ‘forall i. A.Ix i => A.UArray i Int -> Int’
        to type ‘forall i. A.Ix i => A.UArray i Elt -> Int’
    Relevant role signatures:
      type role A.Ix nominal
      type role A.UArray nominal nominal
    When deriving the instance for (A.IArray A.UArray Elt)

虽然 7.10 的发行说明没有提及,但我明白了 https://ghc.haskell.org/trac/ghc/ticket/9220#comment:11 承认这是一个重大变化。但是解决方案是什么——我真的必须为 MyArr 创建一个新类型的包装器,并为每次使用提供帮助函数吗?

【问题讨论】:

  • 有趣。也许UArray 从元素的代表角色转变为名义角色?我想知道为什么。
  • 是的,看起来你会的(vector 的另一个论点 - 获取 UnBox 实例要容易得多)。即使您想通过IArray UArray Elt 实例来unsafeCoerce,您也不能这样做,因为您需要实现的方法不会被导出。虽然我理解为什么我们不应该在这里接地,但我们不能手写IArray 的实例这一事实让我有点不高兴......
  • 您可以从Data.Array.Base导入方法。
  • @ReidBarton 哦。出于某种原因,我认为这没有暴露。谢谢!
  • @ReidBarton,我认为必要的Coercions 应该从GHC.ArrData.Array.Unsafe 或诸如此类导出。这不会给我们 GND,但会让我们coerce 方法。

标签: haskell types coercion


【解决方案1】:

您不必为MyArr 创建包装器,但您必须手动写出您之前派生的实例。一个蛮力解决方案是手动通过IArray 实例unsafeCoerce (你不能coerce 的原因与你不能推导的原因是一样的)。

{-# LANGUAGE InstanceSigs, ScopedTypeVariables, MultiParamTypeClasses #-}

import Data.Array.Base
import Data.Array.IArray
import Data.Array.Unboxed
import Unsafe.Coerce

instance IArray UArray Elt where
  bounds :: forall i. Ix i => UArray i Elt -> (i, i)
  bounds arr = bounds (unsafeCoerce arr :: UArray i Int)                                                                                                                                                                        

  numElements :: forall i. Ix i => UArray i Elt -> Int
  numElements arr = numElements (unsafeCoerce arr :: UArray i Int)

  unsafeArray :: forall i. Ix i => (i,i) -> [(Int, Elt)] -> UArray i Elt
  unsafeArray lu ies = unsafeCoerce (unsafeArray lu [ (i,e) | (i,Elt e) <- ies ] :: UArray i Int) :: UArray i Elt

  unsafeAt :: forall i. Ix i => UArray i Elt -> Int -> Elt
  unsafeAt arr ix = Elt (unsafeAt (unsafeCoerce arr :: UArray i Int) ix) 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-04
    • 1970-01-01
    • 2016-06-26
    • 1970-01-01
    • 2018-07-03
    • 1970-01-01
    • 2012-02-20
    • 2019-01-08
    相关资源
    最近更新 更多