2015-06-26 56 views
1

我是haskell的新手,我正在使用PostgreSQL数据库上的Groundhog-ORM库。如果我将所有数据库内容放入单个函数中,Everythings都可以正常工作。但是,现在我想要在不同的功能中分开不同的主题。Haskell Groundhog-Db函数类型

{-# LANGUAGE GADTs, TypeFamilies, TemplateHaskell, QuasiQuotes, FlexibleInstances, StandaloneDeriving #-} 

module Main where 

import System.IO 
import Database.Groundhog.TH 
import Database.Groundhog.Postgresql 
import Data.DateTime 
import Data.List.Split (splitOn) 
import Control.Monad (mapM_, when, unless) 
import Control.Monad.IO.Class (liftIO) 

postgres_connection_string = "host=localhost port=5432 user=itsme password=unknown dbname=stocks" 

data Symbol = Symbol { 
    name :: String 
} deriving (Show, Eq) 

mkPersist defaultCodegenConfig [groundhog| 
definitions: 
    - entity: Symbol 
    dbName: symbols 
    schema: stocks 
    keys: 
     - name: unique_symbol 
    constructors: 
     - name: Symbol 
     uniques: 
      - name: unique_symbol 
      fields: [name] 
|] 


ensureSymbol :: (PersistBackend m) => String -> m (Symbol) 
ensureSymbol sym = do 
    loadedSymbols <- select (NameField ==. sym) 
    return (loadedSymbols !! 0) 

main = do 
    contents <- readFile "src\\inputTable.csv" 
    putStrLn ("Read " ++ show (length contents) ++ " Bytes input data.") 
    withPostgresqlConn postgres_connection_string . runDbConn $ do 
     liftIO $ putStrLn "About to ensure table structures." 
     runMigration $ do 
      migrate (undefined :: Symbol) 
     liftIO $ putStrLn "Checking for the symbol." 
     symbol <- ensureSymbol "EURUSD" 
     ... [ Some more stuff ] ... 

正如您所看到的,我已经分离了一个从数据库中读取符号实体的小函数。这个例子编译好吧。

然而,函数被调用ensureSymbol而不是readSymbol,因此函数应该读

ensureSymbol :: (PersistBackend m) => String -> m (Symbol) 
ensureSymbol sym = do 
    loadedSymbols <- select (NameField ==. sym) 
    when (null loadedSymbols) (return (Symbol sym)) 
    unless (null loadedSymbols) (return (loadedSymbols !! 0)) 

但现在我得到了一堆错误信息,甚至在线路

loadedSymbols <- select (NameField ==. sym) 

而此前正确编译。我想我需要一个额外的类型说明符来使whenunless对函数可见,但我不确定。

src\Main.hs:117:40: 
    Couldn't match type `Symbol' with `()' 
    In the first argument of `select', namely `(NameField ==. sym)' 
    In a stmt of a 'do' block: 
     loadedSymbols <- select (NameField ==. sym) 
    In the expression: 
     do { loadedSymbols <- select (NameField ==. sym); 
      when (null loadedSymbols) (return (Symbol sym)); 
      unless (null loadedSymbols) (return (loadedSymbols !! 0)) } 

src\Main.hs:118:40: 
    Couldn't match expected type `()' with actual type `Symbol' 
    In the first argument of `return', namely `(Symbol sym)' 
    In the second argument of `when', namely `(return (Symbol sym))' 

src\Main.hs:119:5: 
    Couldn't match type `()' with `Symbol' 
    Expected type: m Symbol 
     Actual type: m() 
    In a stmt of a 'do' block: 
     unless (null loadedSymbols) (return (loadedSymbols !! 0)) 
    In the expression: 
     do { loadedSymbols <- select (NameField ==. sym); 
      when (null loadedSymbols) (return (Symbol sym)); 
      unless (null loadedSymbols) (return (loadedSymbols !! 0)) } 

也许有更好的方法来做到这一点?

回答

0

whenunless都具有相同的类型:

when, unless :: Monad m => Bool -> m() -> m() 

所以你传递的第二个参数值的类型必须是m()。两种情况下你都通过m Symbol。看起来你只是想用if

ensureSymbol sym = do 
    loadedSymbols <- select (NameField ==. sym) 
    if (null loadedSymbols) then (return (Symbol sym)) else (return (loadedSymbols !! 0)) 

case

ensureSymbol sym = do 
     loadedSymbols <- select (NameField ==. sym) 
     case loadedSymbols of 
      [] -> return (Symbol sym) 
      s:ss -> return s 
+0

哎哟,不错。你是对的。典型的noob错误:-)谢谢你。 – Hennes