2013-04-12 5 views
6

私はHaskellのLLVMバインディングを使い始めようとしています。始めるには、こんにちはワールドです。Haskell LLVM bindingあいまいなタイプ

以下は、製本の著者によるブログのものです。

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' in the constraint: (type-level-0.2.4:Data.TypeLevel.Num.Sets.NatI n0) arising from a use of getElementPtr0' 考えられる修正を:これらの型変数(複数可)を修正するタイプの署名を追加」を得る。ここ

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

これはタイプミスで0を忘れる可能性がありますか? getElementPtr0 < - ?私はちょうどここで推測しています。 –

+0

いいえ2つの異なる機能があります。 getElementPtr0はデフォルト値を使用します.getElementPtrはそうではありません。したがって、余分な引数です。また、エラーは、私は確かに、typeclassものです。それ(GHC)は、私にそれをより具体的なものに伝えたいと思っています。私はそれが何を望んでいるのか分かりませんでした。 –

+0

多分http://hpaste.org/完全なものだから、プロがそれと一緒にすることができます:) –

答えて

1

大丈夫です。だから私は問題を解決した。それは確かに典型的なものです。そしてそれは私だけをもっと混乱させました。しかし、私は解決策への答えを持っています。しかし、私の理解を助けるために自由に感じてください。まず、いくつかの掘削。関数createStringNulは、タイプが

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

ファインです。コンパイラが持っていた問題は、Array型の "n"があいまいであることです。それは文字通り世界の何かになる可能性があります。検索、アレイは、あなたとは、今ではそれほど明白ではありませんが、少し掘削時に、特定のWRT getElementPtrへの呼び出しで、1は、nが、本当にあるナットnは、あるべきことを見つけ

newtype Array n a 

を見ます配列のサイズを固定する型レベルの方法です。さて、Array n aの定義は、実際には[a]の型の同義語ではありません。したがって、D0、D9、または Data.TypeLevel.Num.Reps パッケージから必要なものを使用することができます。配列のサイズを固定していますが、この機能では実際には考えられませんでした。しかし、とにかく、変更する greetz < - createStringNul "こんにちは、世界!" 〜 greetz < - createStringNul "Hello、World!" :: TGlobal(配列D0ワード8) が動作します。

ここは面白い部分です...私はそれが動作するとは思わなかった。 D0は0であるはずなので、なぜ0サイズの "Array"にたくさんの文字を格納できるのか理解できませんでした。しかし、ソースコードを見れば、タイプ制限が実際にはないことがすぐに分かりますに注意を払った。

コンパイル時には、createStringNulは非推奨であり、代わりにwithStringNulが代わりに使用されることがわかります。私はwithStringNulの型がどのように動作するかを完全には理解していません。

1

createStringNulis marked as deprecatedllvm(3.0.1.0)の最新版です。 withStringNul使用: - 参照withStringNul :: String -> (forall n . Nat n => Global (Array n Word8) -> a) -> a:最初の例では、エラーを引き起こすものに関しては

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は、より多くの有益なタイプを持っているという事実に関連していますcreateStringNul :: String -> TGlobal (Array n Word8)になります。 withStringNulの関数引数にはhigher-rank typeが含まれています。つまり、nのすべての関数が有効です。つまり、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 

:*型コンストラクタcomes from the type-level packageとタイプレベルの番号を構築するために使用されます。 D1 :* D3は、配列のサイズが13であることを意味します。

+0

それは私がした直後に投稿されたようです。私は本質的にあなたが言ったことを理解していた。しかし、問題は、withStringNul ... with関数を使用することです。第2引数は、構築されているCodeGenModule全体でなければなりません。もし使用することが非常に不自然であれば。 –

+0

@ArmUser 'withStringNul'の関数引数は'(forall n。Nat n => Global(Array n Word8) - > a) '型です。戻り値の型は 'a'です。これは任意の型であり、必ずしも' CodeGenModule'とは限りません。 'createFunction'の型の' CodeGenModule'は、モナド計算コンテキストです。 'createFunction'自体が' Function'を返しますが、モジュールの外で関数を作成することはできないので、 'createFunction'は' CodeGenModule'モナドの中で実行されます。 –

+0

@ArmUser一般的に、これは非常に自然なハスケルのイディオムです。 Cf。 '' with.File'(http://hackage.haskell.org/packages/archive/base/latest/doc/html/System-IO.html#v:withFile)を 'System.IO'に追加してください。 –

関連する問題