RDFS: subClassOf, type, and "multiple inheritance." - object

The Setup
Consider a design where I have a 2 executable programs, foo and bar. Assume both are a subClassOf SW e.g. (and dropping most prefixing for clarity):
SW rdf:type rdfs:Class
foo rdf:type rdfs:Class
foo rdfs:subClassOf SW
bar rdf:type rdfs:Class
bar rdfs:subClassOf SW
SPARQLing with the Jena default reasoner does the expected thing so you can, for example, ask for all things of subClassOf SW and get foo and bar, and you can get all the properties of the super/subclasses, etc. OK. Consider foo and bar to be "atoms"; that is, there is only one each of them. But they could be deployed multiple times. How do we well-segregate the atom info from the per-instance info? Initially, one might try "single inheritance"; here are two such instances of foo:
foo_111 rdf:type rdfs:Class
foo_111 rdfs:subClassOf foo
foo_222 rdf:type rdfs:Class
foo_222 rdfs:subClassOf foo
The problem is now when we ask for all our software atoms (SW) we also pick up the instances thereof which is not what we want. It is probably possible to filter out instances in some way. One way might be with a "marker class", sort of like multiple inheritance:
foo_111 rdf:type rdfs:Class
foo_111 rdfs:subClassOf foo
foo_111 rdfs:subClassOf Instance
foo_222 rdf:type rdfs:Class
foo_222 rdfs:subClassOf foo
foo_222 rdfs:subClassOf Instance
and the query would filter anything of type Instance.
Let's keep exploring for the moment.
An alternate approach is to have an Instance be its own class and have a field named exec which references the thing being activated as a Instance:
Instance rdf:type rdfs:Class
foo_111 rdf:type rdfs:Class
foo_111 rdfs:subClassOf Instance
foo_111 exec foo
foo_222 rdf:type rdfs:Class
foo_222 rdfs:subClassOf Instance
foo_222 exec foo
This is tidy because is cleanly separates the "atom" space from the "instance" space and all sorts of things can become instances. But : Now it seems I cannot SPARQL for all my SW, e.g.
?s rdfs:subClassOf Instance ;
exec SW .
I'm not really surprised because the type/subClassOf machinery isn't looking for a property called exec to work the magic. Note that SPECIFIC values for exec work fine, e.g.
?s rdfs:subClassOf Instance ;
exec foo .
But that is of course way too restrictive/specific; we cannot name every possible piece of software.
The Question
Are there any design best practices in this space that make simple things simple (e.g. "find all SW atoms that EOL in 180 days", which if it yielded 6 pieces of software, we don't want to drag in the 12000 instances of those 6 pieces of software).

Your conceptualization is incorrect. An object is either a concept (class) or an individual, and it depends on the granularity of your knowledge base. In this case, SW is a class, foo and bar are subclasses of SW, and foo_111 and foo_222 are individuals of the foo class. Do not create the class Instance. Instead, use the rdf:type predicate to instantiate the software tools, and use the rdfs:subclassOf predicate in the SPARQL filter to find all software tools. If you need to query instances, use a datatype property to capture a unique identifier, say the barcode of particular copies of the software, and query the value of that property.

Related

How to collect values spread throughout a Haskell codebase

I have a web application written in Haskell (using ghcjs on the client side and ghc on the server side) and I need a way to collect the CSS values which are spread throughout the modules. Currently I use a technique involving a CssStyle class and template haskell. When a module needs to export some CSS it creates a CssStyle instance for some type (the type has no significance except that it must be unique.) In the top level all the CssStyle instances are retrieved using the reifyInstances function from template haskell.
This approach has at least two drawbacks: You have to create meaningless types to attach the instances to, and you have to be sure all the instances are imported in the place where you scan and turn into real CSS. Can anyone think of a more beautiful way to collect data embedded in Haskell code?
================
Quelklef has requested some source code demonstrating the current solution:
{-# LANGUAGE AllowAmbiguousTypes, OverloadedStrings, MultiParamTypeClasses, TemplateHaskell, LambdaCase, FunctionalDependencies, TypeApplications #-}
import Clay
import Control.Lens hiding ((&))
import Data.Proxy
import Language.Haskell.TH
class CssStyle a where cssStyle :: Css
-- | Collect all the in scope instances of CssStyle and turn them into
-- pairs that can be used to build scss files. Result expression type
-- is [(FilePath, Css)].
reifyCss :: Q Exp
reifyCss = do
insts <- reifyInstances ''CssStyle [VarT (mkName "a")]
listE (concatMap (\case InstanceD _ _cxt (AppT _cls typ#(ConT tname)) _decs ->
[ [|($(litE (stringL (show tname))), $(appTypeE [|cssStyle|] (pure typ)))|] ]
_ -> []) insts)
data T1 = T1
instance CssStyle T1 where cssStyle = byClass "c1" & flexDirection row
data T2 = T2
instance CssStyle T2 where cssStyle = byClass "c2" & flexDirection column
-- Need to run this in the interpreter because of template haskell stage restriction:
--
-- > fmap (over _2 (renderWith compact [])) ($reifyCss :: [(String, Css)])
-- [("Main.T2",".c2{flex-direction:column}"),("Main.T1",".c1{flex-direction:row}")]
The point here is that any CssStyle instance from any module imported here will appear in this list, not only those defined locally.
Hmm...
I do not officially recommend your current approach. It's making use of typeclasses in a highly unorthodox way, so it's unlikely to act exactly as you like. As you've already noted, in order for it to work you need to make sure that all CssStyle instances are in scope, which is pretty arcane behaviour. Also, the current approach does not compose well, by which I mean that your css-related computation is all happening in the global context.
Unfortunately, I don't know of any canonical way to do what you want at compile-time.
However, I do have one idea. Most programs run in top-level "industrial" monads, and I'm assuming your program does as well. You could wrap your industrial monad with a new applicative (not monad) F. The role of this applicative is to allow subprograms to propagate their CSS needs to callers. Concretely, there would be a function style :: Css -> F () which acts akin to how tell acts in a writer monad. There would also be affordances to embed actions from your industrial monad into F. Then each module which has its own CSS exports its API wrapped F; doing this tracks the CSS requirements. There would be a function compileCss :: F a -> Css which builds the composite CSS style and does not execute any effectful operations embedded within F. Additionally, there would be a function execute :: F a -> IO a which executes the actions embedded in the F a value. Then main could make use of compileCss to emit the CSS, and make use of execute to separately run the program.
I admit this is somewhat awkward... wrapping all your existing code in F will be annoying at best. However, I do think it is at least correct, insofar as it tracks effects.
Perhaps the proper answer is to use an existing component-based web framework, which allows you define your component markup and styling in the same place? Some of them support emitting to static HTML.

Universally quantified (or polymorphic) type class instances

Is it possible to define a generic type class instance parameterized by a type a in Haskell?
For example:
data Box a = Box a deriving Show
class Boxable a where
create :: a -> Box a
-- pseudo syntax here
instance forall a . Boxable a where
create = Box
If no, why not?
I am aware of the fact that this example is rather simple and "useless". I just want to know whether this is theoretically possible, not whether its practically relevant.
Your code is literally legal Haskell, nothing “pseudo syntax” about it. It's not quite Haskell98, but with two very harmless syntactic extensions it does compile:
{-# LANGUAGE ExplicitForall, FlexibleInstances #-}
data Box a = Box a deriving Show
class Boxable a where
create :: a -> Box a
instance forall a . Boxable a where
create = Box
The -XExplicitForall† is required for the explicit forall (duh), but actually you don't even need this because Haskell type variables are by default universally quantified:
{-# LANGUAGE FlexibleInstances #-}
instance Boxable a where
create = Box
Except, like chepner already commented this doesn't really make sense, because now create behaves just like a regular parametric function without any typeclass needed:
create' :: a -> Box a
create' = Box
That said, such once-and-for-all instances can actually be useful, if you constrain them with some superclass:
class Foo a
class Bar a
class (Foo a, Bar a) => FooBar a
instance (Foo a, Bar a) => FooBar a
Now if you mention FooBar (someComplicatedType) in a function's constraints, it has the same effect as writing out (Foo (someComplicatedType), Bar (someComplicatedType), which can significantly de-clunk your code and error messages and also make your projects more future-safe, because you can add or remove superclasses to FooBar without changing the signatures of all the functions that have this constraint.
(A very similar thing can be achieved with -XConstraintKinds as the arguably more straightforward constraint synonym type FooBar a = (Foo a, Bar a), but this brings in the well-known problem that type isn't really an encapsulation at all but can be unravelled by the compiler at any time, which isn't normally much of a problem except it leads to much more confusing type error messages.)
†You won't find -XExplicitForall itself very often in Haskell files, because it's only really needed as part of either -XScopedTypeVariables or -XRankNTypes, both of which are common and enable the forall keyword, or ∀ as I prefer to write it (which additionally requires -XUnicodeSyntax).

DeriveAnyClass vs Empty Instance

Suppose that I have this type family that throws a custom type error during compile time if the type passed to it is not a record:
type family IsRecord (a :: Type) where
...
Now I have this type class that has methods with default implementations, but requires that the type is a record, by adding the IsRecord constraint:
class IsRecord a => Foo a where
foo :: Text
foo = "foo"
When trying to use it incorrectly, if we use it as a regular instance with a type that is not a record, it successfully fails to compile:
data Bar = Bar
instance Foo Bar -- error: Bar is not a record
But if I enable -XDeriveAnyClass and add it to the deriving clause, this doesn't fail to compile, ignoring completely the constraint:
data Bar = Bar
deriving (Foo)
I understand that DeriveAnyClass generates an empty instance declaration, which is what I'm doing on the first example, but still it doesn't throw the error. What's going on?
I'm using GHC 8.6.4
Wow! I was going to mark this as a duplicate of What is the difference between DeriveAnyClass and an empty instance?, but it seems the behavior of GHC has changed since that question was asked and answered!
Anyway, if you ask -- either with :i inside ghci or with -ddump-deriv before starting ghci -- what the compiler has done, it's clear what the difference is in your case:
> :i Bar
data Bar = Bar -- Defined at test.hs:15:1
instance IsRecord Bar => Foo Bar -- Defined at test.hs:16:13
Indeed, if you change the non-DeriveAnyClass version of your code to match, writing
instance IsRecord Bar => Foo Bar
instead of
instance Foo Bar
everything works fine. The details of how this instance context was chosen seem a bit complicated; you can read what the GHC manual has to say about it here, though I suspect the description there is either not quite precise or not complete, as I don't get the same answer the compiler does here if I strictly follow the rules stated at the documentation. (I suspect the true answer is that it writes the instance first, then just does the usual type inference thing and copies any constraints it discovers in that way into the instance context.)

HASKELL - Change Type

I need to create a function f:: Log->[String] that does that (((o, i ,d),s) = [(o, i ,d)]
type Log = (Plate, [String])
type Plate = (Pin, Pin, Pin)
type Pin = (Char, Int)
If you're on a page like this, click "Source" on the fir right side, next to the function that you're interested in.
If you need to look up a function, Hayoo! and Hoogle will link you to documentation pages like the one above.
An important thing to note, though is that show doesn't have one definition. show is a function defined for all data types in the Show (with a capital "S") typeclass. So for example, here is the full source for the Show typeclass. Show is defined within the typeclass as just show :: a -> String. But if you search for "instance Show Bool" or "instance Show Int", you'll find specific definitions.
For the second part of your question, the easiest way to get a show function for a new type is to simply write deriving (Show) below it. For example,
data Foo = Foo Int Int
deriving (Show)
Now I can use show on data with type Foo.
g :: Log -> [String]
g (plate, _) = [show plate]
Use hoogle to find this sort of information.
Example: http://www.haskell.org/hoogle/?hoogle=show
Once you've found the function you'd like in the list, click and there you'll find a Source link on the right hand side of the page.
NB this is an answer to the original question:
Where can I see the codes of the predefined functions in haskell ?? Mainly the function SHOW?
It's true that you can use Hoogle to search for functions defined in the Prelude (and other modules), but the source code itself is located at Hackage.
Hackage is a database of Haskell packages. You can download new packages from it, and also view the Haddock documentation for every package in the database.
This is the Haddock page for the standard Prelude. It documents the type classes, data types, types, and top-level functions exported by the Prelude module. To the right of each definition header is a link that says "Source". You can click this to be taken to an online copy of the source code for the module you're viewing.
On preview, you're now asking a different question entirely, and on preview again in fact the original question has been edited out of this post.
Your new question is unclear, but this solution will work to produce the output in your example.
> [fst ((('O',0),('I',0),('D',1)),"O->D")]
[(('O',0),('I',0),('D',1))]
I think you're using list notation instead of double quotes to identify Strings, by the way, so I fixed that around 0->D above. So you might also try this instead.
> show (fst ((('O',0),('I',0),('D',1)),"O->D"))
"(('O',0),('I',0),('D',1))"
This works because you have only defined type synonyms (by using type in your declarations instead of data) on data structures which already have Show instances.

How to get rid of this ambiguity?

I am pretty sure this has been asked before, however I was unable to find the right answer:
I tried to eliminate the ambiguity in the following exemplary code snippet:
{-# LANGUAGE MultiParamTypeClasses #-}
class FooBar a b where
foo :: a -> a
foo = id
bar :: a -> a
bar = foo -- ERROR AT THIS LINE
I get an error message like so:
Ambiguous type variable `b0' in the constraint:
(FooBar a b0) arising from a use of `foo'
Probable fix: add a type signature that fixes these type variable(s)
In the expression: foo
In an equation for `bar': bar = foo
which is understandable. Note however, that I'm actually unable to follow the compiler's advice and fix the type variable in question: foo doesn't contain b type variable in its type signature. Also this doesn't work:
bar = (foo :: FooBar a b => a -> a) -- ERROR, the same error message
Not even with -XScopedTypeVariables enabled.
How to tell GHC which FooBar to use? Is it even possible?
EDIT
Following some answers: yes, I've heard about both functional dependencies and associated types.
As to functional dependencies - I am looking for a way to explicitly inform GHC which instance to use (as opposed to asking it to derive the correct type all by itself).
As to both - in the real world example that this one comes from, I actually need both of the parameters a and b to be independent.
Again: I know this example is extremely silly, I know b is not used in the body of the type class, which makes no sense. This is an extreme simplification of a real world example, that actually does make sense. The real use-case involves "substitutability" of types a using types b and then "unifiability" of types a and b using types c and unfortunately is much longer.
EDIT(2)
Okay sorry. I think you convinced me after all that I have to refactor the code in order not to have any ill-defined functions (i.e. ones that don't contain all the independent types in their type signatures). Talking to you really helped me think this thing though. Appreciated.
Your class is ill-defined even if you remove bar completely from the class. Let's just assume you have the following class:
class FooBar a b
where
foo :: a -> a
foo = id
Suppose now you would like to use foo outside the definition of this class.
e = .... foo x .....
GHC will complain with a similar error message than yours, that it can't find a type for b. Simply because your code doesn't supply such a type. Your type class declaration says every pair of types a and b might get an instance. So, even when a is fixed in a call of foo there are still arbitrary many possible instances to select from.
A functional dependency a -> b would solve that problem, because it states: Given a type a there may be only one instance of Foobar a b. An associated type avoids the problem by not using multi-parameter type classes.
regarding the OP's EDIT:
If you insist on having two type parameters. Then every method's signature of the type class has to contain every type variable of the class. There is no way around it.
If you introduce a functional dependency, class FooBar a b | a -> b where, that would settle it, but without that (or associated types), I think it is impossible to resolve the instance to use.
Oh, one way, but kind of ugly: introduce a dummy parameter of type b
class FooBar a b where
foo' :: b -> a -> a
foo' _ = id
bar' :: b -> a -> a
bar' b = foo b

Resources