Haskell LLVM绑定模糊类型

Jon*_*her 6 haskell ffi llvm

我正在尝试开始使用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
Run Code Online (Sandbox Code Playgroud)

它不编译.
相反,我得到"模糊类型变量n0' in the constraint: (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
Run Code Online (Sandbox Code Playgroud)

第一个似乎更自然.我的问题是第一个是什么模糊,我该如何解决它.我的第二个问题是为什么第二个问题不明确.

Jon*_*her 1

好的。所以我解决了这个问题。这确实是一个类型类的东西。这只会让我更加困惑。不过,我确实有解决方案的答案。但请随时帮助我理解。首先,进行一些挖掘。函数 createStringNul 具有类型

createString :: String -> TGlobal (Array n Word8)
Run Code Online (Sandbox Code Playgroud)

美好的。编译器遇到的问题是数组类型中的“n”不明确。它实际上可以是世界上的任何东西。查找、数组,然后你就看到了

newtype Array n a
Run Code Online (Sandbox Code Playgroud)

现在不是那么明显了,但是经过一点挖掘,特别是对 getElementPtr 的调用,我们发现 n 实际上应该是 Nat n,这是一种固定数组大小的类型级方法。现在,数组 na 的定义实际上并不关心它实际上只是 [a] 的类型同义词。因此,您可以使用 D0、D9 或 Data.TypeLevel.Num.Reps 包中您想要的任何内容。固定数组的大小,虽然这个函数实际上没有考虑到一个好主意。但无论如何,改变greetz <- createStringNul“Hello, World!” 问候 <- createStringNul "你好,世界!" :: TGlobal(数组 D0 Word8)有效。

这是有趣的部分......我没想到它会起作用。D0 应该是 0,所以我不明白为什么它允许我在 0 大小的“数组”中存储这么多字符但是,如果你查看源代码,你会立即清楚类型限制实际上并不存在关注了。

好吧,无论如何,在编译后,人们意识到 createStringNul 已被弃用,而 withStringNul 是首选。但我不完全理解 withStringNul 的类型是如何工作的。