Chris Bolton
Chris Bolton

Reputation: 2926

Having trouble defining a new type

ok, so here's my current code:

import Database.MongoDB
import System.IO
import System.Environment
import Data.UString

data Project = Project { name :: String , desc :: String
                       , category :: String , priority :: Int
                       , repeating :: Bool , done :: Bool } deriving (Show)

data Command m = Save ((DbAccess m) => (Collection -> Document -> m ()))

main = do
  pool <- newConnPool 1 $ host "127.0.0.1"
  (command:args) <- getArgs
  let add = Save $ save (u "projects") [(u "name") =: (u $ Prelude.concat args)]
--  let remove = delete (select [(u "name") =: (u $ Prelude.concat args)] (u "projects"))
  let update = Save $ save (u "projects") [(u "name") =: (u $ Prelude.concat args)]
  let commands = [("add", add),("update", update)]
  let (Just (Save action)) = Prelude.lookup command commands
  db <- access safe Master pool $ use (Database (u "test")) action
  print db

My basic problem is that the three possible outcomes for the user's command are either add, update, or remove (I'm messing around with MongoDB.)

Basic syntax for calling the script is ./script {add|update|remove} project name goes here

Add and update have the same return type, but remove has a different one, and since they have different type signatures, haskell's type checking isn't accepting it. I figured I'd have to make a new type to encapsulate both possibilities, as I kind of tried to do above, but I'm not getting anywhere. I'm also very new to haskell and programming in general, so excuse the messy code and possibly noobish question.

Upvotes: 1

Views: 270

Answers (2)

max taldykin
max taldykin

Reputation: 12908

I don't understand why you say that remove has different type. save and delete have different types, but after applying arguments they both return DbAccess m => m ().

import Database.MongoDB
import System.Environment


commands :: DbAccess m => [String] -> [(String, m ())]
commands args = [("add", add),("update", update),("remove",remove)]
  where
    uargs = u $ Prelude.concat args
    add    = save (u "projects") [u "name" =: uargs]
    update = save (u "projects") [u "name" =: uargs]
    remove = delete $ select [u "name" =: uargs] (u "projects")


main = do
  pool <- newConnPool 1 $ host "127.0.0.1"
  (command:args) <- getArgs
  let (Just action) = Prelude.lookup command $ commands args
  db <- access safe Master pool $ use (Database (u "test")) action
  print db

Upvotes: 1

Tarrasch
Tarrasch

Reputation: 10557

Maybe you could have data Command2 with two constructs, say Save1 and Save2. The first encapsulates add/update and the other remove.

Some changes you then need to apply is something like this:

let commands = [("add", Save1 add),("update", Save1 update), ("remove", Save2 remove)]

And instead of use you can maybe define something like this:

use2 db (Save1 action)  = use db action
use2 db (Save2 action)  = use db action

For everything to work you would also need to change the lookup to this.

let (Just action) = Prelude.lookup command commands

Note that I removed Save pattern matcher now.

I hope this helps. :)

Upvotes: 1

Related Questions