migrating elixir 1.0 app to 1.2 and having issues with derive Collectable for module struct - upgrade

The 1.0 implementation looks like this.
defmodule Chat do
use GenServer
#derive [Access, Collectable]
defstruct [api: APIClient, chat_id: nil, clients: %{}]
def start_link(params), do: GenServer.start_link(__MODULE__, params)
def init(params) do
state = Enum.into(params, %__MODULE__{})
{:ok, state}
end
...
end
First problem is that Access has been deprecated, does that mean I have to change the dot notation when accessing state fields?
Second problem is that if I don't remove the #derive Collectable I get this error Collectable.Any is not available, cannot derive Collectable ....
Here params is a keyword list, I supose I could convert the keyword list to a Map with state = Map.merge(%__MODULE__{}, Enum.into(params, %{})) but feels terribly clumsy.

I'm not sure about the particular Collectable issue, but there's a much better solution to your particular problem - constructing a struct from a list of key-value pairs.
You can use Kernel.struct/2 for that. It won't only construct the struct for you, but also validate the keys, and use only those that really are in the struct. Since 1.2 there's Kernel.struct!/2 that will raise in case any of the provided keys is invalid.

Related

Unique symbol value on type level

Is it possible to have some kind of unique symbol value on the type level, that could be used to distinct (tag) some record without the need to supply a unique string value?
In JS there is Symbol often used for such things. But I would like to have it without using Effect, in pure context.
Well, it could even like accessing Full qualified module name (which is quite unique for the task), but I'm not sure if this is a really relevant/possible thing in the Purescript context.
Example:
Say There is some module that exposes:
type Worker value state =
{ tag :: String
, work :: value -> state -> Effect state
}
makeWorker :: forall value state. Worker value state
performWork :: forall value state. woker -> Worker value state -> value -> Unit
This module is used to manage the state of workers, it passes them value and current state value, and gets Effect with new state value, and puts in state map where keys are tags.
Users of the module:
In one module:
worker = makeWorker { tag: "WorkerOne", work }
-- Then this tagged `worker` is used to performWork:
-- performWork worker "Some value"
In another module we use worker with another tag:
worker = makeWorker { tag: "WorkerTwo", work }
So it would be nice if there would be no need to supply a unique string ("WorkerOne", "WorkerTwo") as a tag but use some "generated" unique value. But the task is that worker should be created on the top level of the module in pure context.
Semantics of PureScript as such is pure and pretty much incompatible with this sort of thing. Same expression always produces same result. The results can be represented differently at a lower level, but in the language semantics they're the same.
And this is a feature, not a bug. In my experience, more often than not, a requirement like yours is an indication of a flawed design somewhere upstream.
An exception to this rule is FFI: if you have to interact with the underlying platform, there is no choice but to play by that platform's rules. One example I can give is React, which uses the JavaScript's implicit object identity as a way to tell components apart.
So the bottom line is: I urge you to reconsider the requirement. Chances are, you don't really need it. And even if you do, manually specified strings might actually be better than automatically generated ones, because they may help you troubleshoot later.
But if you really insist on doing it this way, good news: you can cheat! :-)
You can generate your IDs effectfully and then wrap them in unsafePerformEffect to make it look pure to the compiler. For example:
import Effect.Unsafe (unsafePerformEffect)
import Data.UUID (toString, genUUID)
workerTag :: String
workerTag = toString $ unsafePerformEffect genUUID

How to use Scala Cats Validated the correct way?

Following is my use case
I am using Cats for validation of my config. My config file is in json.
I deserialize my config file to my case class Config using lift-json and then validate it using Cats. I am using this as a guide.
My motive for using Cats is to collect all errors iff present at time of validation.
My problem is the examples given in the guide, are of the type
case class Person(name: String, age: Int)
def validatePerson(name: String, age: Int): ValidationResult[Person] = {
(validateName(name),validate(age)).mapN(Person)
}
But in my case I already deserialized my config into my case class ( below is a sample ) and then I am passing it for validation
case class Config(source: List[String], dest: List[String], extra: List[String])
def vaildateConfig(config: Config): ValidationResult[Config] = {
(validateSource(config.source), validateDestination(config.dest))
.mapN { case _ => config }
}
The difference here is mapN { case _ => config }. As I already have a config if everything is valid I dont want to create the config anew from its members. This arises as I am passing config to validate function not it's members.
A person at my workplace told me this is not the correct way, as Cats Validated provides a way to construct an object if its members are valid. The object should not exist or should not be constructible if its members are invalid. Which makes complete sense to me.
So should I make any changes ? Is the above I'm doing acceptable ?
PS : The above Config is just an example, my real config can have other case classes as its members which themselves can depend on other case classes.
One of the central goals of the kind of programming promoted by libraries like Cats is to make invalid states unrepresentable. In a perfect world, according to this philosophy, it would be impossible to create an instance of Config with invalid member data (through the use of a library like Refined, where complex constraints can be expressed in and tracked by the type system, or simply by hiding unsafe constructors). In a slightly less perfect world, it might still be possible to construct invalid instances of Config, but discouraged, e.g. through the use of safe constructors (like your validatePerson method for Person).
It sounds like you're in an even less perfect world where you have instances of Config that may or may not contain invalid data, and you want to validate them to get "new" instances of Config that you know are valid. This is totally possible, and in some cases reasonable, and your validateConfig method is a perfectly legitimate way to solve this problem, if you're stuck in that imperfect world.
The downside, though, is that the compiler can't track the difference between the already-validated Config instances and the not-yet-validated ones. You'll have Config instances floating around in your program, and if you want to know whether they've already been validated or not, you'll have to trace through all the places they could have come from. In some contexts this might be just fine, but for large or complex programs it's not ideal.
To sum up: ideally you'd validate Config instances whenever they are created (possibly even making it impossible to create invalid ones), so that you don't have to remember whether any given Config is good or not—the type system can remember for you. If that's not possible, because of e.g. APIs or definitions you don't control, or if it just seems too burdensome for a simple use case, what you're doing with validateConfig is totally reasonable.
As a footnote, since you say above that you're interested in looking in more detail at Refined, what it provides for you in a situation like this is a way to avoid even more functions of the shape A => ValidationResult[A]. Right now your validateName method, for example, probably takes a String and returns a ValidationResult[String]. You can make exactly the same argument against this signature as I have against Config => ValidationResult[Config] above—once you're working with the result (by mapping a function over the Validated or whatever), you just have a string, and the type doesn't tell you that it's already been validated.
What Refined allows you to do is write a method like this:
def validateName(in: String): ValidationResult[Refined[String, SomeProperty]] = ...
…where SomeProperty might specify a minimum length, or the fact that the string matches a particular regular expression, etc. The important point is that you're not validating a String and returning a String that only you know something about—you're validating a String and returning a String that the compiler knows something about (via the Refined[A, Prop] wrapper).
Again, this may be (okay, probably is) overkill for your use case—you just might find it nice to know that you can push this principle (tracking validation in types) even further down through your program.

Update deeply nested case class with Options

I have a 3-level nested case class model with a bunch of options that represents some data in a database. It's essentially:
case class User(settings: Option[Settings])
case class Settings(keys: Option[List[KeySet]])
case class KeySet(privateKey: String, publicKey: String)
I understand how to get deeply nested fields out of this using some for comprehension or chains of flatMap (Scala Option object inside another Option object) and I also understand how to update it using a lens library, but I want to figure out how to update the fields even if some stuff in the tree is None and automatically make Somes of those if they don't exist yet.
For example, how would I handle the case where I want to add to the keys List but the user hasn't yet set any settings? Is it possible to, in some sense, automatically create a Some(settings) field and also a Some(keys) field?
I have an idea of how to do it with a lot of pattern matching, but this seems wrong because of 1. rightward drift of code and 2. not using map or flatMap very much with the options.
Is this possible using a lens library on its own? I read here that it might not be possible: https://github.com/julien-truffaut/Monocle/issues/215 as in the case of Monocle it can't update an Option that is a None. Maybe I need to think about the problem another way?
Thanks
I'm not sure why you use Option[List[KeySet]]. Is there an important distinction between None and an empty List?
In any case, I find fold to be a handy tool when working with Options.
def updateUser(u :User, ks :KeySet) :User = {
u.copy(settings =
Some(u.settings.fold(Settings(Some(ks::Nil))) (stngs =>
stngs.copy(keys = Some(stngs.keys.fold(ks::Nil) (ks::_))))))
}
val pat = updateUser(User(None), KeySet("a","b"))
//pat: User = User(Some(Settings(Some(List(KeySet(a,b))))))
val upat = updateUser(pat, KeySet("c","d"))
//upat: User = User(Some(Settings(Some(List(KeySet(c,d), KeySet(a,b))))))

How to Typecheck a DefDef

Within an annotation Macro, I'm enumerating members of a class and want the types of the methods that I find.
So I happily iterate over the body of the class, and collect all the DefDef members.
... which I can't typecheck.
For each DefDef I've tried wrapping it in an Expr and using actualType. I've tried duplicating the thing and transplanting it into an ad-hoc class (via quasiquotes). I've tried everything else I can think of :)
The best I can get is either NoType or Any, depending on the technique used. The worst I get is to have an exception thrown at me.
These are simple methods, of the form def foo(i: String) = i, so the return type needs to be inferred, but there's no external information required. There are no abstract types, or type params, or other members of the class involved here. I'd like to handle more advanced cases later, but want to have these trivial examples working first.
In a plugin, this would be simple. I'd just typecheck the entire unit with errors suppressed and get at what I want through the symbols, then reset the tree attributes for subsequent processing. As a macro... I'm stumped.
What am I missing?
In a macro it's the same. Instead of typed as in plugins, you call c.typeCheck, but have to be careful not to fall into a trap (https://github.com/scalamacros/paradise/issues/1) that is supposed to be fixed in 2.10.5 and 2.11.0. After a successful return from a c.typeCheck, you can get access to the symbol and do all the usual stuff.

Configuration data in Scala -- should I use the Reader monad?

How do I create a properly functional configurable object in Scala? I have watched Tony Morris' video on the Reader monad and I'm still unable to connect the dots.
I have a hard-coded list of Client objects:
class Client(name : String, age : Int){ /* etc */}
object Client{
//Horrible!
val clients = List(Client("Bob", 20), Client("Cindy", 30))
}
I want Client.clients to be determined at runtime, with the flexibility of either reading it from a properties file or from a database. In the Java world I'd define an interface, implement the two types of source, and use DI to assign a class variable:
trait ConfigSource {
def clients : List[Client]
}
object ConfigFileSource extends ConfigSource {
override def clients = buildClientsFromProperties(Properties("clients.properties"))
//...etc, read properties files
}
object DatabaseSource extends ConfigSource { /* etc */ }
object Client {
#Resource("configuration_source")
private var config : ConfigSource = _ //Inject it at runtime
val clients = config.clients
}
This seems like a pretty clean solution to me (not a lot of code, clear intent), but that var does jump out (OTOH, it doesn't seem to me really troublesome, since I know it will be injected once-and-only-once).
What would the Reader monad look like in this situation and, explain it to me like I'm 5, what are its advantages?
Let's start with a simple, superficial difference between your approach and the Reader approach, which is that you no longer need to hang onto config anywhere at all. Let's say you define the following vaguely clever type synonym:
type Configured[A] = ConfigSource => A
Now, if I ever need a ConfigSource for some function, say a function that gets the n'th client in the list, I can declare that function as "configured":
def nthClient(n: Int): Configured[Client] = {
config => config.clients(n)
}
So we're essentially pulling a config out of thin air, any time we need one! Smells like dependency injection, right? Now let's say we want the ages of the first, second and third clients in the list (assuming they exist):
def ages: Configured[(Int, Int, Int)] =
for {
a0 <- nthClient(0)
a1 <- nthClient(1)
a2 <- nthClient(2)
} yield (a0.age, a1.age, a2.age)
For this, of course, you need some appropriate definition of map and flatMap. I won't get into that here, but will simply say that Scalaz (or Rúnar's awesome NEScala talk, or Tony's which you've seen already) gives you all you need.
The important point here is that the ConfigSource dependency and its so-called injection are mostly hidden. The only "hint" that we can see here is that ages is of type Configured[(Int, Int, Int)] rather than simply (Int, Int, Int). We didn't need to explicitly reference config anywhere.
As an aside, this is the way I almost always like to think about monads: they hide their effect so it's not polluting the flow of your code, while explicitly declaring the effect in the type signature. In other words, you needn't repeat yourself too much: you say "hey, this function deals with effect X" in the function's return type, and don't mess with it any further.
In this example, of course the effect is to read from some fixed environment. Another monadic effect you might be familiar with include error-handling: we can say that Option hides error-handling logic while making the possibility of errors explicit in your method's type. Or, sort of the opposite of reading, the Writer monad hides the thing we're writing to while making its presence explicit in the type system.
Now finally, just as we normally need to bootstrap a DI framework (somewhere outside our usual flow of control, such as in an XML file), we also need to bootstrap this curious monad. Surely we'll have some logical entry point to our code, such as:
def run: Configured[Unit] = // ...
It ends up being pretty simple: since Configured[A] is just a type synonym for the function ConfigSource => A, we can just apply the function to its "environment":
run(ConfigFileSource)
// or
run(DatabaseSource)
Ta-da! So, contrasting with the traditional Java-style DI approach, we don't have any "magic" occurring here. The only magic, as it were, is encapsulated in the definition of our Configured type and the way it behaves as a monad. Most importantly, the type system keeps us honest about which "realm" dependency injection is occurring in: anything with type Configured[...] is in the DI world, and anything without it is not. We simply don't get this in old-school DI, where everything is potentially managed by the magic, so you don't really know which portions of your code are safe to reuse outside of a DI framework (for example, within your unit tests, or in some other project entirely).
update: I wrote up a blog post which explains Reader in greater detail.