是否有一种灵活的方法来指定Haskell';s型家庭?
最近我开始使用Haskell的Repa库,它严重依赖于和相关的类型。我可以这样定义一个Repa数组:是否有一种灵活的方法来指定Haskell';s型家庭?,haskell,type-families,repa,Haskell,Type Families,Repa,最近我开始使用Haskell的Repa库,它严重依赖于和相关的类型。我可以这样定义一个Repa数组: ghci> let x = fromListUnboxed (Z :. (5 :: Int) :. (2 :: Int)) [1..10] ghci> computeP $ R.map id x :: IO (Array U DIM2 Double) AUnboxed ((Z :. 5) :. 2) (fromList [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.
ghci> let x = fromListUnboxed (Z :. (5 :: Int) :. (2 :: Int)) [1..10]
ghci> computeP $ R.map id x :: IO (Array U DIM2 Double)
AUnboxed ((Z :. 5) :. 2) (fromList [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0])
ghci> computeP $ R.map id x :: Shape sh => IO (Array U sh Double)
并对其进行如下操作:
ghci> let x = fromListUnboxed (Z :. (5 :: Int) :. (2 :: Int)) [1..10]
ghci> computeP $ R.map id x :: IO (Array U DIM2 Double)
AUnboxed ((Z :. 5) :. 2) (fromList [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0])
ghci> computeP $ R.map id x :: Shape sh => IO (Array U sh Double)
其中U是关联的数据类型,它将导致结果表示为未绑定数组;DIM2是数组维度。我不喜欢这样,我必须指定一个具体的维度,即使它可以被推断出来。相反,我想写这样的东西:
ghci> let x = fromListUnboxed (Z :. (5 :: Int) :. (2 :: Int)) [1..10]
ghci> computeP $ R.map id x :: IO (Array U DIM2 Double)
AUnboxed ((Z :. 5) :. 2) (fromList [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0])
ghci> computeP $ R.map id x :: Shape sh => IO (Array U sh Double)
这是无效的,但我的目的是通过传递适当的关联数据类型(本例中为U)来指定数组类型,但保持形状不变。这样做可能吗?这样做行吗
asArrayU :: Array U sh a -> Array U sh a
asArrayU = id
computeP $ asArrayU <$> R.map id x
asArrayU::数组usha->数组usha
asArrayU=id
计算$asArrayU R.map id x
您的示例
ghci> computeP $ R.map id x :: Shape sh => IO (Array U sh Double)
不起作用,因为在这里您声明结果值是多态的,可以具有任何可能的形状,但这显然是不真实的,因为x
具有特定的形状,因此结果只能具有相同的特定形状,即DIM2
您可以说,computeP
和R.map id
的组合保留了相同的形状,而不管最初的形状是什么。即
ghci> (computeP . R.map id :: Shape sh => Array U sh Double -> IO (Array U sh Double)) x
AUnboxed ((Z :. 5) :. 2) (fromList [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0])
这里重要的一点是,我们将表示锁定为非固定值,因为这是编译器无法自动确定的部分
但是如果不了解您的实际用例,就很难从语法上说什么是表达您想要的最好的选项。您主要对在GHCi中测试东西感兴趣,而不指定显式类型,还是希望避免在实际程序中的某个地方显式键入
例如,您可以定义如下内容
computeMap :: (Unbox a, Unbox b, Shape sh) => (a -> b) -> Array U sh a -> IO (Array U sh b)
computeMap f = computeP . R.map f
然后你可以说
ghci> computeMap id x
AUnboxed ((Z :. 5) :. 2) (fromList [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0])
不,但这是:asArrayU(computeP$R.map id x)谢谢!我想知道是否还有其他方法来解决这个问题。@killy9999:请注意,
Prelude
包含,这是这种方法的一个通用版本。因此,即使有其他方法,这一方法也肯定是经典的@C.A.McCann叹息,另一个如何帮助haskell的类型推断记住的骗局:-/我怀疑这是正确的方法。最后,代码变得更复杂,可读性更低。实际上,这更能满足我的好奇心。感谢您向我展示了其他方法:)