我试图解决当我使用Haskell llvm绑定时发生的编译时错误.
代码:
-- Line 14 follows
type Acc = Int32 -> Int32 -> IO Int32
type Sig = Int32 -> Ptr Int32 -> Function Acc-> IO Int32
-- [...]
-- Line 31 follows
mSum :: CodeGenModule (Function Sig)
mSum = createNamedFunction ExternalLinkage "sum" $ \l ptr_x fn -> do
r <- forLoop (valueOf 0) l (valueOf (0::Int32)) $ \i sum -> do
xi <- getIndex ptr_x i
x <- load xi
call fn sum x
ret r
Run Code Online (Sandbox Code Playgroud)
注释:mSum是一个monadic函数,它为llvm函数生成一个咬合代码.生成的函数用于获取三个参数:: l整数数组的长度; ptr_x指向整数数组的指针; 和fn一个功能.(第32行)生成的函数将循环遍历数组的元素和调用的累加器sum.对于每一个值,x,sum和x将被传递给函数fn.该函数的结果将成为sum下一次循环的值.sum的最终值将作为生成函数的值返回.
错误:
llvm3.hs:32:8:
Context reduction stack overflow; size = 21
Use -fcontext-stack=N to increase stack size to N
$dFunctionArgs :: FunctionArgs
(Function Acc -> b17)
(Value (Ptr (Int32 -> Int32 -> IO Int32)) -> b'17)
r18
$dFunctionArgs :: FunctionArgs
(Ptr (Int32 -> Int32 -> IO Int32) -> b16)
(Value (Function Acc) -> b'16)
r17
-- [ ... ]
$dFunctionArgs :: FunctionArgs
(Ptr (Int32 -> Int32 -> IO Int32) -> b4)
(Value (Function Acc) -> b'4)
r5
$dFunctionArgs :: FunctionArgs
(Function Acc -> b3)
(Value (Ptr (Int32 -> Int32 -> IO Int32)) -> b'3)
r4
$dFunctionArgs :: FunctionArgs
(Ptr (Int32 -> Int32 -> IO Int32) -> b2)
(Value (Function Acc) -> b'2)
r3
$dFunctionArgs :: FunctionArgs
(Function Acc -> IO Int32)
(Function (Int32 -> Int32 -> IO Int32)
-> CodeGenFunction r Terminate)
(CodeGenFunction r0 ())
$dFunctionArgs :: FunctionArgs
(Ptr a0 -> b1) (Value (Ptr Int32) -> b'1) r2
$dFunctionArgs :: FunctionArgs
(Ptr Int32 -> Function Acc -> IO Int32)
(Value (Ptr a0)
-> Function (Int32 -> a0 -> IO Int32)
-> CodeGenFunction r Terminate)
(CodeGenFunction r0 ())
$dFunctionArgs :: FunctionArgs (i0 -> b) (Value Int32 -> b') r1
$dFunctionArgs :: FunctionArgs
Sig
(Value i0
-> Value (Ptr a0)
-> Function f0
-> CodeGenFunction r19 Terminate)
(CodeGenFunction r0 ())
In the expression: createNamedFunction ExternalLinkage "sum"
In the expression:
createNamedFunction ExternalLinkage "sum"
$ \ l ptr_x fn
-> do { r <- forLoop (valueOf 0) l (valueOf (0 :: Int32))
$ \ i sum -> ...;
ret r }
In an equation for `mSum':
mSum
= createNamedFunction ExternalLinkage "sum"
$ \ l ptr_x fn
-> do { r <- forLoop (valueOf 0) l (valueOf (0 :: Int32)) $ ...;
.... }
Run Code Online (Sandbox Code Playgroud)
问题:有两个可能的问题:如果我没有正确传递函数,那么如何将指针传递给LLVM中的函数?否则我需要做什么来满足类型检查器?
旁白:我不太了解Haskell的工作,足以理解我为什么会遇到这个错误.我也不明白类型签名createNamedFunction:
(IsFunction f, FunctionArgs f g (CodeGenFunction r ()))
=> Linkage
-> String
-> g -- Function body.
-> CodeGenModule (Function f)
Run Code Online (Sandbox Code Playgroud)
哦,好悲伤.
是的,您可能有某种类型错误.这里的库UndecidableInstances用来做一些花哨的类型级逻辑,其中"花哨"意味着"如果你不走运,会导致类型检查器进入无限循环".你可能猜到你现在有多幸运.不幸的是,而造成令人震惊的错误告诉我们这里的循环正在发生,它不是知识性为一体的想了解为什么.
此外,请注意,不理解为什么会出现此错误是完全合理的.这是混乱和混乱.接下来是一些粗略的解释和我对缩小原因的看法:
首先,循环显然是在计算时发生的FunctionArgs.考虑类的定义:
class FunctionArgs f g r | f -> g r, g r -> f where
...
Run Code Online (Sandbox Code Playgroud)
后面的部分|是功能依赖,指定某些参数唯一地确定其他参数.在这种情况下,f以及彼此的组合g和r确定,所以它是一种可以在任一方向上计算的双向函数.
你的功能mSum :: CodeGenModule (Function Sig),与签名统一的createNamedFunction给我们Sig作为f参数,以r和g目前未知.类型同义词Sig扩展为Int32 -> Ptr Int32 -> Function Acc-> IO Int32.现在,我们可以看一下实例列表的FunctionArgs,看看这给了我们.
运算符优先级给我们最左边的函数箭头作为最外面的类型构造函数Sig,因此我们找到匹配的实例:FunctionArgs b b' r => FunctionArgs (a -> b) (Value a -> b') r.我们可以在类型中替换,根据需要进行统一,并重复:
FunctionArgs (Ptr Int32 -> Function Acc-> IO Int32) b' r => FunctionArgs (Int32 -> (Ptr Int32 -> Function Acc-> IO Int32)) (Value Int32 -> b') r
FunctionArgs (Function Acc-> IO Int32) b' r => FunctionArgs (Ptr Int32 -> (Function Acc-> IO Int32)) (Value (Ptr Int32) -> b') r
您应该能够将这些步骤与您收到的错误中的堆栈跟踪相匹配.一个有趣的事情是,堆栈跟踪中有额外的步骤,我不确定其原因 - 与我基于功能依赖性填充类型的方式有关,我想.看起来它首先根据(->)类型构造函数选择实例,然后填充参数的Value a -> b类型构造g函数,然后在返回统一其余类型之前执行递归步骤(在上下文中).
现在,我们知道在这一点上出现问题的时候; 这可以从堆栈溢出的通用原理推断出来,即问题就在堆栈跟踪开始反复重复相同模式之前的某个地方.
对于下一次减少,f实例化为Function Acc-> IO Int32,同时g并且r到目前为止仍未确定(尽管我们知道它们必须由唯一确定f).Function在这一点上看一下这个定义也许是一个好主意:type Function a = Value (Ptr a)
FunctionArgs (Value (Ptr Acc) -> IO Int32) g r我们再次使用函数箭头选择实例: FunctionArgs b b' r => FunctionArgs (a -> b) (Value a -> b') r
......这是哪里有鬼发生的,因为如果你比较上面的堆栈跟踪,它显示(Function (...) -> ...)的g参数.在技术上匹配给定Function上面的定义,因为我们期望Value,这是Function类型同义词的最外层构造函数.不幸的是,我们也有(Function (...) -> ...)对f参数,这是不一致的,因为g参数应该有一个额外的Value构造函数.
在填入不正确的结构之后,它继续卡在应该填充剩余类型变量的步骤; 它看起来好像双向函数依赖使其来回反弹,多次试图统一a使用Value a.因此,随着类型同义词的扩展,我们得到:
FunctionArgs (Value (Ptr Acc) -> b) (Value (Ptr Acc) -> b') rFunctionArgs (Ptr Acc -> b) (Value (Value (Ptr Acc)) -> b') r......无限的.
在这一点上,我真的不确定会导致这场冲突的原因.我期望的结果将是一致的实例选择FunctionArgs (Value (Ptr Acc) -> b) (Value (Value (Ptr Acc)) -> b') r,我不能真正说出为什么它会被卡住.
编辑:等等,我很傻.我最初误读了你的代码 - 很明显从lambda表达式的推断类型得到了错误类型的一部分,我认为它比实际上更具多态性.特别是,该参数fn作为函数的参数给出call :: CallArgs f g => Function f -> g,这是创建上述不一致类型的参数.我仍然不知道为什么它会进入无限循环,但至少可以解释冲突.
在假设由于推断类型call是正确的,g参数应该有类型Value Int32 -> Value (Ptr Int32) -> Function Acc-> CodeGenFunction Int32 (),这意味着f应Int32 -> Ptr Int32 -> Ptr Acc-> IO Int32,而不是你的类型Sig.
Bolstering这是说,如果你看一下IsFunction类,这也适用于f,它期望的函数参数是原始类型,如Int32或Ptrs到原始类型,但不Value,这是Function扩展到.
毕竟,我认为你的问题只是你的类型Sig有点错误.
...韦尔普.好吧.
| 归档时间: |
|
| 查看次数: |
561 次 |
| 最近记录: |