Conditional module aliasing - module

For a class project I am writing a program that evaluates the performance of different implementations of the same abstract data structure. Since I am using identical code to test each of them, I would like to be able to set a module alias depending on user input and just run that module through the testing code.
In other words, I want something like:
let module M =
if model = "tree" then TreeModel else
if model = "hash" then HashModel else
ListModel
in ...
Is there a way I can make this work, or am I going about this all wrong?

There are no conditionals on the module level, but you can use first-class modules for this:
let m = match model with
| "tree" -> (module TreeModel : MODEL)
| "hash" -> (module HashModel : MODEL)
| "list" -> (module ListModel : MODEL)
in let module M = (val m : MODEL)
in ...

As a follow-up to #Andreas, at least in recent ocaml versions you can also write:
let (module M : MODEL) = match model with
| "tree" -> (module TreeModel : MODEL)
| "hash" -> (module HashModel : MODEL)
| "list" -> (module ListModel : MODEL)
in ...

Related

Update record field from Collection

I am playing a little bit with Elm these days, but I stuck with a simple case where I want to update a record field. My code is like this:
-- MODEL
initialModel : Model
initialModel =
{ selectedLanguage = "german"
, allCards = Card.cards
}
type alias Msg =
{ description : String
, data : String
, id : String
}
The update function
update : Msg -> Model -> Model
update msg model =
case List.head (model.allCards) of
Just card ->
{ card | fliped = True }
Nothing -> model
but I see this:
Something is off with the 1st branch of this `case` expression:
50| { card | fliped = True }
^^^^^^^^^^^^^^^^^^^^^^^^
The 1st branch is a record of type:
{ back : String, fliped : Bool, front : String, id : String }
But the type annotation on `update` says it should be:
Model
Hint: Seems like a record field typo. Maybe back should be allCards?
Hint: Can more type annotations be added? Type annotations always help me give
more specific messages, and I think they could help a lot in this case!
Detected errors in 1 module.
I think I should always return a model from update function like my type says, but cannot figure out how. Any advice here?
You'll have update the allCards field of model too. You can nest the card update inside the model update if the former returns a list instead of just a single card:
update : Msg -> Model -> Model
update msg model =
{ model
| allCards =
case model.allCards of
card :: rest ->
{ card | fliped = True } :: rest
[] ->
[]
}
Or you can bind the new allCards to a name if you prefer:
update : Msg -> Model -> Model
update msg model =
let
newAllCards =
case model.allCards of
card :: rest ->
{ card | fliped = True } :: rest
[] ->
[]
in
{ model | allCards = newAllCards }
I pattern match directly on the list here instead of using List.head, as that also gives me the remainder of the list and I don't have to deal with an intermediary Maybe value (or two actually, since List.tail returns a Maybe as well). The card::rest branch hits if allCards contains at least one card, so the only remaining case is therefore [], which is easy enough to handle.
Also, flipped is spelled with two ps ;)

How can the `Msg` type be separated into many types in Elm?

The standard way to use model and update in Elm is to define the Model and Msg types, and the update function:
type alias Model = { ... }
type Msg = Msg1 | Msg2 | ...
update : Msg -> Model -> (Model, Cmd Msg)
...
When the application grows, all those types and functions become more complex. I'd like to separate them in the following way:
type alias Model1 = { ... }
type alias Model2 = { ... }
type alias Model = { model1 : Model1, model2 : Model2 }
type Msg1 = Msg1a | Msg1b | ...
type Msg2 = Msg2a | Msg2b | ...
type Msg = M1 Msg1 | M2 Msg2 | ...
Then, I'd like to handle all of them separately (and I know how to do it).
I have a problem with the view function, though. I define my view as follows:
view : Model -> Html Msg
view model =
let v1 = view1 model.model1
...
in ...
view1 : Model1 -> Html Msg1
view1 model = ...
The problem is, the result of view1 is Html Msg1, and the view function needs Html Msg.
Is there a way to convert the result from Html Msg1 to Html Msg?
You're looking for Html.map:
view : Model -> Html Msg
view model =
let v1 = view1 model.model1 |> Html.map M1
v2 = view2 model.model2 |> Html.map M2
in ...

How to accomplish inheritance in Elm

type alias Car = { model : Model, year: Int }
type Model = Crv | Enzo | Mustang | Viper
-- I can do this
enzo = Car Enzo -- partial Contructor
> myE<function> : Int -> Repl.Car
myEnzo = enzo 2018
> { model = Enzo, year = 2018 } : Repl.Car
-- but i CANNOT do this
enzo2017 = Car { year: 2017 } -- INVALID
How can i make a simple constructor that doesn't force me to list the attributes in a defined order.
When it comes to functional programming we need to "start over" with some concepts. In this case the confusion seems to be with the word constructor.
The record constructor in Elm is different than the object constructor in object oriented language.
The record constructor does not create a record, it only creates a function that can create records. It does this by partial application.
In partial application you can only give the arguments in their order. This is defined in lambda calculus and I believe it is not specific to Elm.
In the case of creating records with record constructor changing the order of the argument doesn't make changes in the result.
We can use this handy function flip that returns the same function with reverse order of the arguments:
enzo2017 = flip Car 2017
myEnzo2017 = enzo2017 Viper
Consider, when you define this:
type alias Car = { model : Model, year: Int, notes: String}
what you really get, is a function Car like this:
> Car
> <function> : Repl.Model -> Int -> String -> Repl.Car
It's easy to define another constructor:
> f notes model year = Car model year notes
> <function> : String -> Repl.Model -> Int -> Repl.Car

How do I merge signals of nested tagged types?

As part of the Elm app I’m building, I want to keep signals of environment changes (like resizing the window) from data changes (rendering a filterable list of models to the browser). I thought I would model these as different extensible types:
type WindowUpdate = Resize (Int, Int)
type DataUpdate = TagFilter Model.Tag
type Update update data = WindowUpdate update data
| DataUpdate update data
| NoOp
updates : Signal.Mailbox (Update update data)
updates = Signal.mailbox NoOp
appModel : Signal Model
appModel =
let
applicationUpdates = Signal.mergeMany
[ updates.signal
]
in
Signal.foldp update Model.defaultModel applicationUpdates
windowUpdate : WindowUpdate -> Model -> Model
windowUpdate update model =
let resizeWidth = \windowModel newWidth -> { windowModel | width = newWidth }
in
case update of
Resize (w, _) -> { model | window = (resizeWidth model.window w) }
update : Update -> Model -> Model
update u model =
case u of
WindowUpdate wu data -> windowUpdate (wu data) model
DataUpdate du data -> model
otherwise -> model
Unfortunately I can’t get my update function to work correctly. I get the following compiler errors:
— TYPE MISMATCH —————————————————————— ./app/Updates.elm
The 3rd argument to function `foldp` is causing a mismatch.
36│ Signal.foldp update Model.defaultModel applicationUpdates
^^^^^^^^^^^^^^^^^^
Function `foldp` is expecting the 3rd argument to be:
Signal (Update a)
But it is:
Signal Update
Hint: I always figure out the type of arguments from left to right. If an
argument is acceptable when I check it, I assume it is "correct" in subsequent checks. So the problem may actually be in how previous arguments interact with the 3rd.
What am I doing wrong?
You forgot the type parameters of Update in the signature of update, it should be (code untested):
update : Update update data -> Model -> Model

Access Instance-property in Coffeescript within nested

so I am using express within a node-app. As my app is getting bigger I want to put my routes into extra files. I seem to be able to get hold of the bugDB if I just get rid of the intermediate get object. But I can't access the bugDB in the inner object. Any suggestions? Maybe there is even a more nice code pattern for how to accomplish this more elegantly.
I would appreachate your help. Thanks in advance. (As I am not a native speaker I couldn't find others with a similar problem, if you know how to phrase the question better, please show me the way :) )
BUGROUTER.COFFEE
class BugsRouter
constructor: (#bugDB)-> // instance-variable with databaselink
return
get:{
allBugs: (req, res)=>
console.log "db", #bugDB // this gives me undefined
// is "this" in the get context?
#bugDB.allDocs {include_docs: true}, (err, response)->
res.json 200, response
}
module.exports = BugsRouter
SERVER.COFFEE
BugsRouter = require "./routes/BUGROUTER"
bugsRouter = new BugsRouter(bugDB)
console.log bugsRouter.bugDB # this is working
app.get "/bugs/all", bugsRouter.get.allBugs
Sub-objects don't work like that. When you say this:
class C
p:
f: ->
Then p is just a plain object that happens to be a property on C's prototype, it will have no special idea of what # should be inside f. And if you try to use a fat-arrow instead:
class C
p:
f: =>
then you're accidentally creating a namespaced class function called f so # will be C when f is called. In either case, saying:
c = new C
c.p.f()
is the same as:
c = new C
p = c.p
p.f()
so f will be called in the context of p rather than c.
You can get around this if you don't mind manually binding the functions inside get when your constructor is called:
constructor: (#bugDB) ->
#get = { }
for name, func of #constructor::get
#get[name] = func.bind(#)
This assumes that you have Function.bind available. If you don't then you can use any of the other binding techniques (_.bind, $.proxy, ...). The #get = { } trick is needed to ensure that you don't accidentally modify the prototype's version of #get; if you're certain that you'll only be creating one instance of your BugsRouter then you could use this instead:
constructor: (#bugDB) ->
for name, func of #get
#get[name] = func.bind(#)
to bind the functions inside the prototype's version of get rather than the instance's local copy.
You can watch this simplified demo to see what's going on with # in various cases, keep an eye on the #flag values to see the accidental prototype modification caused by not using #get = { } and #constructor::get:
class C1
get:
f: -> console.log('C1', #)
class C2
get:
f: => console.log('C2', #)
class C3
constructor: ->
#flag = Math.random()
for name, func of #get
#get[name] = func.bind(#)
get:
f: -> console.log('C3', #)
class C4
constructor: ->
#flag = Math.random()
#get = { }
for name, func of #constructor::get
#get[name] = func.bind(#)
get:
f: -> console.log('C4', #)
for klass in [C1, C2, C3, C3, C4, C4]
o = new klass
o.get.f()
Live version of the above: http://jsfiddle.net/ambiguous/8XR7Z/
Hmm, seems like I found a better solution after all:
class Test
constructor: ->
#testVariable = "Have a nice"
return
Object.defineProperties #prototype,
get:
enumerable :true
get:->
{
day: => #testVariable + " day"
week: => #testVariable + " day"
}
console.log (new Test()).get.day()
This allows me to call (new Test()).get.day() the way I wanted.
Live version at: JSFiddle