Haskell LLVM绑定模糊类型

6

我试图开始使用Haskell的LLVM绑定。一个很好的起点是Hello World。

以下内容来自绑定作者的博客。

bldGreet :: CodeGenModule (Function (IO ()))
bldGreet = do
    puts <- newNamedFunction ExternalLinkage "puts" :: TFunction (Ptr Word8 -> IO Word32)
    greetz <- createStringNul "Hello, World!"
    func <- createFunction ExternalLinkage $ do
      tmp <- getElementPtr greetz (0::Word32, (0::Word32, ()))
      call puts tmp -- Throw away return value.
      ret ()
    return func

无法编译。
而是得到了“约束中的模糊类型变量n0': (type-level-0.2.4:Data.TypeLevel.Num.Sets.NatI n0) arising from a use ofgetElementPtr0' 可能的解决方法:添加一个类型签名,以修复这些类型变量”

这里有一个可以工作的变体

llvmModule :: TFunction (IO Word32)
llvmModule = 
    withStringNul "Hello world!" $ \s -> do 
    puts <- newNamedFunction ExternalLinkage "puts" :: TFunction (Ptr Word8 -> IO Word32)
    main <- newNamedFunction ExternalLinkage "main" :: TFunction (IO Word32)
    defineFunction main $ do
      tmp <- getElementPtr0 s (0::Word32, ())
      _ <- call puts tmp
      ret (0::Word32)
    return main

第一个句子似乎更自然。我的问题是第一个句子的歧义在哪里,以及如何解决。我还想知道为什么第二个句子不会产生歧义。


这可能是一个打错字并忘记加0的情况吗?getElementPtr0<-?我只是猜测。 - Gert Cuykens
不是的。有两个不同的函数。getElementPtr0使用默认值,而getElementPtr则不使用--因此需要额外的参数。此外,我相当确定错误是类型类的问题。 GHC希望我告诉它更具体的关于类型类的信息。我只是还没有弄清楚它想要什么。 - Jonathan Gallagher
也许你可以将整个 http://hpaste.org/ 的内容都贴出来,这样专业人士就可以调试它了 :) - Gert Cuykens
2个回答

1

好的。所以我解决了问题。确实是一个类型类的问题。这让我更加困惑了。但是,我有一个解决方案的答案。但请随意帮助我理解。首先,我们需要进行一些挖掘。函数createStringNul的类型为

createString :: String -> TGlobal (Array n Word8)

好的。编译器遇到的问题是Array类型中的“n”是不明确的。它可以是世界上任何东西。查找Array,你会看到。
newtype Array n a

现在并不是很明显,但经过一点挖掘,特别是关于getElementPtr的调用,人们发现n实际上应该是Nat n,这是一种固定数组大小的类型级方式。现在,Array n a的定义实际上并不关心它,它只是[a]的类型同义词。因此,您可以使用Data.TypeLevel.Num.Reps包中的D0、D9或任何您想要的东西。虽然固定数组的大小是个好主意,但这个函数实际上没有考虑到它。但无论如何,将 "greetz <- createStringNul"Hello, World!"更改为"greetz <- createStringNul"Hello, World!" :: TGlobal (Array D0 Word8)即可正常工作。
这里有趣的部分是......我没想到它会起作用。D0应该是0,所以我不理解为什么它允许我在大小为0的"Array"中存储那么多字符。然而,如果您看源代码,就会立即清楚类型限制实际上并没有被注意到。
好的,无论如何,编译后,人们意识到createStringNul已经过时,应该使用withStringNul代替。但我并不完全理解withStringNul的类型是如何工作的。

1
在当前版本的llvm(3.0.1.0)中,createStringNul被标记为过时,使用withStringNul代替。点击此处查看
import Data.Word
import LLVM.Core

bldGreet :: CodeGenModule (Function (IO ()))
bldGreet = do
    puts <- newNamedFunction ExternalLinkage "puts" :: TFunction (Ptr Word8 -> IO Word32)
    func <- withStringNul "Hello, World!" $ \greetz ->
      createFunction ExternalLinkage $ do
        tmp <- getElementPtr greetz (0::Word32, (0::Word32, ()))
        _ <- call puts tmp -- Throw away return value.
        ret ()
    return func

关于第一个示例中引起错误的原因,与 withStringNul 具有更详细类型相关:withStringNul :: String -> (forall n . Nat n => Global (Array n Word8) -> a) -> a -- cf. to createStringNul :: String -> TGlobal (Array n Word8)withStringNul 的函数参数具有更高秩类型 - 这意味着该函数适用于所有自然数n
如果您真的想使用createStringNul,您可以为greetz添加显式类型签名来使第一个示例编译通过:
{-# LANGUAGE TypeOperators #-}
module Test
       where

import Data.Word
import Data.TypeLevel.Num.Reps
import LLVM.Core

bldGreet :: CodeGenModule (Function (IO ()))
bldGreet = do
    puts <- newNamedFunction ExternalLinkage "puts" :: TFunction (Ptr Word8 -> IO Word32)
    greetz <- createStringNul "Hello, World!"
    func <- createFunction ExternalLinkage $ do
      tmp <- getElementPtr (greetz :: Global (Array (D1 :* D3) Word8)) (0::Word32, (0::Word32, ()))
      call puts tmp -- Throw away return value.
      ret ()
    return func
< p > :* 类型构造函数 来自类型级包,用于构造类型级数字。 D1 :* D3 表示数组大小为 13。


看起来你是在我之后发布的。我已经基本上理解了你所说的。然而,问题在于要使用withStringNul函数...第二个参数必须是正在构建的整个CodeGenModule。这感觉非常不自然。 - Jonathan Gallagher
@MikhailGlushenkov 很好,这里有一个可以编译llvm-3.2.0.2包的版本:https://gist.github.com/robstewart57/7194104。我的问题是:如何扩展它,使`bldGreet`接受一个字符串,并在“Hello”之后打印它,例如“Hello Joe!”。类似于bldGreet :: CodeGenModule(Function(String-> IO()))。我该如何扩展bldGreet来实现这一点? - Rob Stewart
@MikhailGlushenkov 我应该补充一下..如果你能构造这个稍微修改过的bldGreet,那么我接下来会问你如何在我的GitHub要点的main函数中将字符串"Joe"作为参数传递给bldGreet - Rob Stewart
1
@RobStewart 像下面这样的代码应该可以工作(未经测试):https://gist.github.com/23Skidoo/7195530 - Mikhail Glushenkov
@MikhailGlushenkov 太好了,谢谢。是的,它编译通过了,并且表现出了我所期望的行为。 - Rob Stewart
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接