Type families in Persistent library - haskell

When explaining the template expansion in the chapter on Persistent, the Yesod book has something looking like
newtype Key Person = PersonKey (BackendKey SqlBackend)
I'm not quite sure how to read this newtype declaration: is
PersonKey a something already defined somewhere else (couldn't
find its definition though) or is PersonKey just an ordinary
type or value constructor like Just/Nothing/Left/etc. ?

Alright, to simplify just a bit first, let's pretend it said:
newtype KeyPerson = PersonKey (BackendKey SqlBackend)
In this case, KeyPerson would be the "type constructor", and PersonKey would be the "data constructor." We would be creating both of them here. The PersonKey data constructor would hold a value of type BackendKey SqlBackend, which would need to exist elsewhere and be referenced from here.
In this case, we're usually associated types (aka type families), which makes things slightly more complicated: newtype Key Person means "we're defining an associated Key for the Person type. But we're still creating a PersonKey data constructor just as before.

Related

How can I use a field from my Persistent model as a path piece in my routes file?

I have a Persistent model like so:
Organization sql=organizations
Id UUID default=uuid_generate_v1mc
name Text
UniqueOrganizationName name
deriving Show Eq Typeable
I'd like to use the organization name in my Yesod routes file like so:
/#OrganizationName/onboarding/business/about OnboardingBusinessAboutR POST
Using OrganizationName or UniqueOrganizationName there gives me this error:
/Users/maximiliantagher/Documents/Mercury/hs/mercury-web-backend/src/Foundation.hs:41:1: error:
• Data constructor ‘OrganizationName’ cannot be used here
(Perhaps you intended to use TypeInType)
• In the type ‘OrganizationName’
In the definition of data constructor ‘OnboardingBusinessAboutR’
In the data instance declaration for ‘Route’
I could use a newtype as a workaround, just wondered if that was necessary.
I imagine the lack of a PathPiece instance is a problem, but if it was just that then the error would be No instance for (PathPiece ...).
Using either OrganizationName or UniqueOrganizationName would be fine.
The OrganizationName type is a constructor, because this is what is used in Persistent machinery like selectList. In reality, name is a parameter of the Organization constructor of type Text, so you just need #Text in your route.

Record syntax field type annotation having only smart constructor

I'm trying to create a record where one of the fields has a type that is not exported, since it's using a smart constructor. Using the smart constructor as the type does not work.
Not in scope: type variable `domain'
Maybe there is a language extension that allows me to do this, or something similar?
Exporting the constructor along with the smart constructor would allow me to solve this problem, but that in turn creates the possibility of creating values that the smart constructor wouldn't allow.
The (non-working) code I have right now:
import Domain (domain) -- Domain is not exported, and domain is a smart constructor for Domain
data Rec = Rec
{ dint :: domain Int -- what do I do here? I want it to be `Domain Int` but `Domain` isn't exported.
...
}
The issue here is confusion between the concept of a type constructor and a data constructor. For brevity, I will illustrate the difference with an example.
data Foo a = Bar [a]
In the expression above, Foo is the type constructor and Bar is the data constructor. The key difference is that Foo is a value in Haskell's type space and Bar is a value in its data space. A value in type space cannot be used in data space, and vice versa. For example, the compiler would error at the following expressions.
someVariable :: Bar Int
someVariable = Foo [15]
The next expression, however, is completely valid.
someVariable :: Foo Int
someVariable = Bar [15]
Additionally, all type constructors must start with an upper case letter. Any types starting with a lower case letter will be considered type variables, not type constructors (the a in our definition above is an example of this).
The introduction of smart constructors add another layer to this problem, but the key thing to understand is that smart constructors are data constructors, not type constructors. In your definition of Rec, you tried to use your smart constructor, domain, in the type declaration for dint field. However, because domain is a data constructor not a type constructor, and it is lower case, the Haskell compiler tried to interpret domain as the name of a type variable. Because you never specified a variable named domain in your definiton of the Rec type, the compiler raised an error.
You don't actually need to export the data constructor for Domain to solve the issue, just the type itself. This can be accomplished with the following.
module Domain (
Domain(), domain,
...
) where
Including Domain() in the export definition tells Haskell to export the Domain type constructor, but not any of its data constructors. This preserves the safety you wanted with the safe constructor, and allows you to define types correctly. You can now use your newly exported type in your definition of Rec.
import Domain (Domain(), domain)
data Rec = Rec
{ dint :: Domain Int
...
}
For more information, I strongly recommend you read the HaskellWiki articles on constructors and smart constructors.

Is there any standard implementation of the "trivial constraint", or "object class"?

I want just
class Trivial t
instance Trivial t
This is of course useless in Haskell 98 since you can just omit the constraint; but with ConstraintKinds we can have explicitly required arguments of kind * -> Constraint. Ideally, I would like to just define this as an "anonymous type-level function" \type a -> (), but that's evidently not possible.
What should I do, use something predefined or just define that class locally right where I need it (as nobody will need to access it because the instance is universal, that seems quite ok as well)?
As this appears to be quite popular, I finally pushed such a trivial-constraint class to a Hackage package.
import Data.Constraint.Trivial
id' :: Unconstrained t => t -> t
id' = id

Interfacing and extending ApplicationClass

I am trying to write a module in F#, making it easier working with Excel, by extracting rows, columns, etc. along with type casting and so on. One of the first things I wanted to do, was to extend various classes/types to implement the IDisposable interface. I tried to write something like the following
type Excel.ApplicationClass with
interface IDisposable with
member this.Dispose() =
this.excel.Quit()
Marshal.ReleaseComObject(this.excel) |> ignore
What I wasn't aware of, was that I would get the following error "All implemented interfaces should be declared on the initial declaration of the type".
My question is the following: Since I am not allow to extend a type with an interface - what else could I do?
If you inherit from the base class it can work, like this
type myAppClass() =
inherit Excel.ApplicationClass() //may not be correct signature - you need to match the base constructor
interface IDisposable with
member this.Dispose() =
//function body

Haskell Inferred instance declaration on inherited classes

I've seen cases of chains of Haskell classes that all "extend" each other (see for example, the widget/container/etc classes in gtk2hs)
class Class1 a where....
class (Class1 a)=>Class2 a where....
class (Class2 a)=>Class3 a where....
....and so on....
where all the class functions have default values that depend on one Class1 function. This works great, but makes for a really ugly "instantiation" of ClassN
Instance Class1 Object where
func x = ....
Instance Class2 Object
Instance Class3 Object
Instance Class4 Object
Instance Class5 Object
....and so on....
(I've seen code just like this in popular hackage libraries, so I'm pretty sure that at the time of the writing of the code this was a proper way to do this).
My question- Are there any newer GHC extensions that would clean this up. I've looked a bit and haven't found any. Ideally, all you really need is to decleare Object as an instance of ClassN, and give the Class1 function, the rest would be inferred.
[preemptive snarky comment :)- This indicates an "object oriented" way of thinking, you should really learn how to program functionally.
My response- I agree it is very object oriented, but code like this exists in the ecosystem today, and might very well be needed, GUI libs like gtk2hs, for example. From a practical viewpoint I need to write code like this sometimes, and I just want to simplify it.]
It is a discussed proposal to add Synonym Instances.
For example it would be possible to write next code:
type Stringy a = (Read a, Show a)
instance Stringy a where
read = ...
show = ...
in this case it would be possible to declare
type ClassAll a = (Class1 a, Class2 a, Class3 a, Class4 a)
instance ClassAll a where
foo = ...
But for now, type constraint could be used in function's signatures only, not in instances.
UPDATED
As Vittor mentions, you can find proposal here: Multi-headed instance declarations
The original proposal is a part of class aliases proposal

Resources