2013-04-12 4 views
6

하스켈에 대한 LLVM 바인딩을 시작하려고합니다. 시작하기에 가장 좋은 곳은 Hello World입니다.하스켈 LLVM 바인딩 모호한 유형

다음은 바인딩 작성자가 작성한 블로그에서 가져온 것입니다.

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 

컴파일되지 않습니다. 여기

작동합니까 변형입니다

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 

첫 번째는 것 같다
대신 나는 "이러한 유형의 변수 (들)을 고정하는 타입의 서명을 추가 모호한 타입 변수가 getElementPtr0 ' 가능성있는 수정 n0' in the constraint: (type-level-0.2.4:Data.TypeLevel.Num.Sets.NatI n0) arising from a use of"GET 더 자연스러운. 내가 가지고있는 질문은 첫 번째 모호성이 무엇인지, 어떻게 해결할 수 있습니까? 두 번째 질문은 왜 두 번째 질문이 모호하지 않은지입니다.

+0

오타가 있거나 0을 잊어 버릴 수 있습니까? getElementPtr0 <-? 나는 여기서 추측하고있다. –

+0

아니요 두 가지 다른 기능이 있습니다. getElementPtr0는 getElementPtr이없는 기본 값을 사용하므로 추가 인수가 사용됩니다. 또한, 오류는, 꽤 확신합니다, typeclass 일입니다. 그것은 (GHC) 내가 typeclass에 대해 좀 더 구체적인 것을 말하기를 바랍니다. 나는 단지 그것이 원하는 것을 알아 내지 못했습니다. –

+0

어쩌면 http://hpaste.org/ 완전한 일 이니까 프로가 그걸로 도울 수 있습니다 :) –

답변

1

오케이. 그래서 나는 그 문제를 해결했다. 참으로 typecass입니다. 그리고 그것은 나를 혼란 시켰을뿐입니다. 그러나 솔루션에 대한 해답이 있습니다. 그러나 내 이해를 돕기 위해 자유롭게 느끼십시오. 첫째, 일부 파기. createStringNul 함수의 유형은

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

파인입니다. 컴파일러가 가지고있는 문제는 Array 타입의 "n"이 모호하다는 것입니다. 그것은 문자 그대로 세계에서 어떤 것도 될 수 있습니다. 조회, 배열, 당신과 지금 그렇게 명확하지 않다, 그러나 약간의 파고에, 특히 WRT getElementPtr에 대한 호출에, 하나는 n이 정말 인 냇 N이어야 것을 발견

newtype Array n a 

참조 배열의 크기를 고정하는 유형 수준의 방법입니다. 이제 Array n의 정의는 실제로 [a]에 대한 유형 동의어입니다. 따라서 D0 또는 D9를 사용하거나 Data.TypeLevel.Num.Reps 패키지에서 원하는 것을 사용할 수 있습니다. 어레이의 크기를 고정하는 반면,이 기능으로는 실제로 좋은 아이디어가 고려되지 않았습니다. 그러나 어쨌든, 변경 greetz < - createStringNul "Hello, World!" ~ greetz < - createStringNul "Hello, World!" :: TGlobal (배열 D0 Word8) 작동합니다.

여기 재미있는 부분이 있습니다 ... 작동하지 않을 것이라고 생각했습니다. D0은 0으로 가정하기 때문에 왜 0 크기의 "Array"에 많은 문자를 저장할 수 있는지 이해할 수 없었습니다. 그러나 소스 코드를 보면 유형 제한이 실제로는 아님이 분명합니다 주의를 기울였다.

무엇이든, 컴파일시에는 createStringNul이 사용되지 않으며 대신에 withStringNul이 선호됩니다. 나는 withStringNul의 타입이 어떻게 작동하는지 완전히 이해하지 않는다.

1

createStringNulis marked as deprecated 현재 버전은 llvm (3.0.1.0)입니다. 참조를 - withStringNul :: String -> (forall n . Nat n => Global (Array n Word8) -> a) -> a : 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이 더 많은 정보 유형이 있다는 사실에 관련이 createStringNul :: String -> TGlobal (Array n Word8). withStringNul의 함수 인수는 higher-rank type입니다.이 함수는 모두 n에 대해 작동합니다. 즉, n은 자연수입니다.

{-# 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 입력 레벨 번호를 구성하는 데 사용됩니다 : 당신이 정말로 createStringNul를 사용하려면

, 첫 번째 예는 greetz에 대한 명시 적 타입 서명을 추가하여 컴파일 할 수 있습니다. D1 :* D3은 배열의 크기가 13임을 의미합니다.

+0

내가 한 직후 게시 한 것 같습니다. 나는 당신이 말한 것을 본질적으로 알아 냈습니다. 그러나 문제는 withStringNul ...이라는 함수를 사용하는 것입니다. 두 번째 인수는 생성되는 전체 CodeGenModule이어야합니다. 만약에 사용하기에 아주 부자연 스러울 때. –

+0

@ArmUser'withStringNul'의 함수 인자는'(forall n. Nat n => Global (Array n Word8) -> a)'형을가집니다. 리턴 타입은'a'이며, 어떤 타입이 될 수 있습니다 - 반드시'CodeGenModule'은 아닙니다. 'createFunction' 타입의'CodeGenModule'은 모나드 계산 컨텍스트입니다. 'createFunction' 자체는'Function'을 리턴합니다 -하지만 모듈 외부에서 함수를 생성 할 수 없기 때문에'createFunction'는'CodeGenModule' 모나드에서 실행됩니다. –

+0

@ArmUser 일반적으로 아주 자연스러운 하스켈 관용구입니다. Cf. System.IO에서 ['withFile'] (http://hackage.haskell.org/packages/archive/base/latest/doc/html/System-IO.html#v:withFile)을 사용하십시오. –