2013-08-07 2 views
2

저는 하스켈을 처음 접했습니다. 스칼라에서 왔습니다. 하스켈을 좋아하지만, persistent을 사용할 때 타입 시스템과 싸우고있는 것처럼 느껴집니다.Haskell + Yesod : Persistent를 사용하여 삽입 로직을 분리하면 컴파일되지 않습니다. 형식을 알아낼 수 없습니다

내 요청 : 일부 삽입 로직을 자체 메소드로 분리하고 싶습니다. 나는 타입이나 올바른 방법을 알 수 없다. 실패한 모든 시도는 컴파일되지 않습니다. 아래의보다 간결한 질문. 그래서, 내 질문

insertArticle :: String -> String -> String -> MaybeT (???) 
insertArticle url title content = do 
    curatorId <- selectFirst [curatorName ==. "Fake Name"] 
    lift $ do 
     curator <- curatorId 
     insert (Article url title content curator) 

을 :

  1. 어떤 종류의에 있어야

    다음
    share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase| 
    Curator 
        name String 
        url String 
        feed String 
        UniqueUrl url 
        deriving Show 
    Article 
        url String 
        title String 
        content String 
        curatorId CuratorId Eq 
        deriving Show 
    |] 
    

    작동하지 않는 시도가 실패한입니다 : 여기

    데이터 선언입니다 ????
  2. lift은 올바른 장소에 있습니까? (일반적으로 컴파일러가 더 유용합니다).
  3. 더 좋은 방법이 있나요?

PS - 필자는 다른 로직을 성공적으로 추상화했습니다. 삽입물은 저를 고통의 세계로 만들고 있습니다. 이 SqlPersistM 모나드에서 Just 삽입 된 자료 또는 Nothing을 반환하기 때문에, insertArticle의 반환 형식이 SqlPersistM (Maybe ArticleId)해야 SqlPersistM

getFeeds :: SqlPersistM [Curator] 
getFeeds = do 
    curatorIds <- selectList [] [Asc CuratorName] 
    let curatorGenerics = map entityVal curatorIds 
    let curators = map (\x -> x :: Curator) curatorGenerics 
    return curators 

답변

1

를 사용하는 동안 나는 그것을 컴파일 얻을 수 없습니다.

insertArticle :: String -> String -> String -> SqlPersistM (Maybe ArticleId) 
insertArticle url title content = do 
    curatorEntity <- selectFirst [CuratorName ==. "Fake Name"] [] 
    for curatorEntity $ \(Entity curatorId _) -> 
     insert (Article url title content curatorId) 

내가 여기 Maybe 값을 selectFirst 반환을 처리하기 위해 Data.Traversable에서 for를 사용

당신은 같은 기능 뭔가를 구현할 수 있습니다.

사실,이 형식 시그니처는 SQL 백엔드를 사용하기 때문에 마음에 들지 않습니다. 좀 더 일반화하기 위해 이와 같은 형식 주석을 작성할 수 있습니다.

insertArticle :: (Applicative m, PersistQuery m, PersistMonadBackend m ~ PersistEntityBackend Curator) => 
       String -> String -> String -> m (Maybe ArticleId) 

서명이 약간 복잡하지만이 기능은 모든 백엔드에서 작동합니다.

그런데 getFeeds을 단순화 할 수 있습니다.

getFeeds :: (Functor m, PersistQuery m, PersistMonadBackend m ~ PersistEntityBackend Curator) => 
      m [Curator] 
getFeeds = map entityVal <$> selectList [] [Asc CuratorName] 
+0

빠른 응답을 보내 주셔서 감사합니다! 어떻게 타입이'SqlPersistT'인지 찾으셨습니까? 좀 더 일반적인'insert' 타입을 사용할 때마다 나는 비참하고 읽을 수없는 타입 문제를 가지고 있습니다. 나는 여전히 해킹에 익숙해 져 있는데, 아마도 'SqlPersistT'를 놓친 것이다. 추신 : 'getFeeds' 개선에 감사드립니다! – aaronlevin

+0

후속 조치 : 타입 서명에서 물결표 ('~')에 대한 더 많은 정보를 어디에서 찾을 수 있는지 알고 있습니까? 그것은'PersistMonadBackend m'이'PersistEntityBackend 큐레이터 '의 동등성 또는 계열에 있다고 말하는 것입니까? – aaronlevin

+1

@weirdcanada :'a ~ b'는 유형 동등 제약 조건입니다. 즉, 'a'와'b' 유형이 동일해야합니다. docs : http://www.haskell.org/ghc/docs/7.4.1/html/users_guide/equality-constraints.html – porges