Is a linked functor a useful abstraction for more type-sensitive DSLs?

Motivation

I am currently working on a small hobby project to try to implement something like TaskJuggler in Haskell, mainly as an experiment for playing with domain language writing.

My current goal is to have a small DSL to create a description Project, as well as an associated Tasks. There is no hierarchy yet, although this will be my next extension. I currently have the following data types:

data Project = Project { projectName :: Text
                       , projectStart :: Day
                       , projectEnd :: Day
                       , projectMaxHoursPerDay :: Int
                       , projectTasks :: [Task]
                       }
  deriving (Eq, Show)

data Task = Task { taskName :: Text }
  deriving (Eq, Show)

Nothing crazy there, I'm sure you will agree.

DSL /. Writer [Task] , . , :

project "LambdaBook" startDate endDate $ do
  task "Web site"
  task "Marketing"

project :: Text -> Date -> Date -> Writer [Task] a, Writer , 8 projectMaxHoursPerDay.

- :

project "LambdaBook" $ do
  maxHoursPerDay 4
  task "Web site"
  task "Marketing"

maxHoursPerDay () Project. Writer , [Task] , .

:

""

Project :

data Project = Project { projectName, projectStart, projectEnd, projectProperties }
data ProjectProperties = ProjectProperties { projectMaxHoursPerDay :: Maybe Int
                                           , projectTasks :: [Task]
                                           }

Monoid ProjectProperties. Writer ProjectProperties, , Project. , , Project ProjectProperties - , .

Semigroup m => Writer m

Project Monoid, , , Semigroup. // First, maxHoursPerDay - Last, projectTasks - [Task]. Writer a Semigroup, Writer.

- "" Monoid - . Project ProjectProperties, . Project - (maxHoursPerDay Just, !).

, , , (- return/pure).

http://hpaste.org/82024 ( ) http://hpaste.org/82025 ( ). , SO- ( ), Resource Task. , , Bind ( Monad) DSL.

, , , .

+5
3
data Project maxHours = Project {tasks :: [Task], maxHourLimit :: maxHours}

defProject = Project [] ()

setMaxHours :: Project () -> Project Double
setMaxHours = ...

addTask :: Project a -> Project a

type CompleteProject = Project Double...

runProject :: CompleteProject -> ...

storeProject :: CompleteProject -> ...

, , , . set unset .

+3

, Google+, Writer, Endo Project. lens DSL:

data Project = Project { _projectName :: String
                       , _projectStart :: Day
                       , _projectEnd :: Day
                       , _projectTasks :: [Task]
                       }
  deriving (Eq, Show)

makeLenses ''Project

task :: String -> ProjectBuilder Task
task name = t <$ mapProject (projectTasks <>~ [t])
  where t = Task name []

DSL. , , , (, , - ).

+1

, , .

? DSL ?

defaultProject
  { projectName = "Lambdabook"
  , projectStart = startDate
  , projectEnd = endDate
  , tasks =
    [ Task "Web site"
    , Task "marketing"
    ]
  }

Tangentially, Racketeer once told me that Haskell has only one macro: syntax do. So, Haskellers train everyone in monads whenever they want to manipulate syntax.

0
source

All Articles