Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是否有一种灵活的方法来指定Haskell';s型家庭?_Haskell_Type Families_Repa - Fatal编程技术网

是否有一种灵活的方法来指定Haskell';s型家庭?

是否有一种灵活的方法来指定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.

最近我开始使用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.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的类型推断记住的骗局:-/我怀疑这是正确的方法。最后,代码变得更复杂,可读性更低。实际上,这更能满足我的好奇心。感谢您向我展示了其他方法:)