Ad Hoc Polymorphism and Type Hierarchy - programming-languages

I'm trying to find out how to determin a blank in the following code
{ classes = [ class E extends _
, class D extends _
, class F extends C
, class C
]
, methods = [ m ( C x, _ y, E z)
, m ( D x, C y, _ z)
, m ( C x, _ y, D z)
, m ( E x, C y, C z)
, m ( F x, C y, _ z)
]
, call = m ( new _ () , new _ () , new E () )
}
such that the set of indices of minimal (most specific)
applicable method declarations (cf. JLS 15.12.2) is
[ _, 3]
Here, e.g., [ _ ] means that exactly one declaration is minimal
and you have to write its index. Indexing starts at 0.
how is it possible to do so?

Related

Beginner to Haskell type system : "Haskell non-type variable argument in constraint" Error

In an attempt to dip my toes in functional programming, I'm attempting to pick up Haskell and running into some mental issues with the type system.
Running the following code gives proper output (e.g. generates coordinates for a circle wrapped around a cylinder of radius R at angle theta):
coilGeneration_AngleTest housingRadius coilWidth coilDepth numEle zoffset centralAngle
= [ (x',y',z)
| theta <- [0,2*pi/(numEle-1)..2*pi]
, let x = housingRadius * cos(coilWidth*cos(theta)/housingRadius)
, let y = housingRadius * sin(coilWidth*cos(theta)/housingRadius)
, let z = coilDepth * sin(theta)+zoffset
, let x' = x * cos(centralAngle) - y * sin(centralAngle)
, let y' = x * sin(centralAngle) + y * cos(centralAngle)
]
Sample coilGeneration_AngleTest function output
However, attempting to generalize this into a function that generates an arbitrary NxM array of circles with varying overlaps in the polar and z-directions by running:
coilArrayGeneration_Test r nE width depth n m mu gam
= [ (x',y',z',i,j)
| theta <- [0,2*pi/(nE-1)..2*pi]
, i <- [1..n]
, j <- [1..m]
, let a = width/2
, let b = depth/2
, let x = r * cos(a*cos(theta)/r)
, let y = r * sin(a*cos(theta)/r)
, let z = b * sin(theta)
, let phi = (2*i-1-n)((a-mu)/r)
, let zo = (2*j-1-m)(b-gam)
, let x' = x * cos(phi) - y * sin(phi)
, let y' = x * sin(phi) + y * cos(phi)
, let z' = z + zo
]
gives the following error:
Build profile: -w ghc-9.2.5 -O1
In order, the following will be built (use -v for more details):
- Haskell-0.1.0.0 (exe:Haskell) (file app/Main.hs changed)
Preprocessing executable 'Haskell' for Haskell-0.1.0.0..
Building executable 'Haskell' for Haskell-0.1.0.0..
[1 of 1] Compiling Main ( app/Main.hs, /Users/zack/Desktop/Udemy/Haskell/dist-newstyle/build/aarch64-osx/ghc-9.2.5/Haskell-0.1.0.0/x/Haskell/build/Haskell/Haskell-tmp/Main.o )
app/Main.hs:66:1: error:
• Non type-variable argument in the constraint: Num (c -> c)
(Use FlexibleContexts to permit this)
• When checking the inferred type
coilArrayGeneration_Test :: forall {c}.
(Floating c, Num (c -> c), Enum c, Enum (c -> c)) =>
c
-> c
-> c
-> c
-> (c -> c)
-> (c -> c)
-> c
-> c
-> [(c, c, c, c -> c, c -> c)]
|
66 | coilArrayGeneration_Test r nE width depth n m mu gam = [(x',y',z',i,j)|theta <- [0,2*pi/(nE-1)..2*pi],....
Failure Output
After googling for a while, it seemed that my function had an improper type implied by the compiler but I unfortunately don't understand the idea Haskell Type Definition well enough to fix it. I attempted to define the types the way I see them, namely:
r -> Double
nE -> Int
width -> Double
depth -> Double
n -> Int
m -> Int
mu -> Double
gam -> Double
x' -> Double
y' -> Double
z' -> Double
I -> Int
j -> Int
Getting:
coilArrayGeneration_Test :: (Floating a, Integral b) => a -> b -> a -> a -> b -> b -> a -> a -> [(a,a,a,b,b)]
coilArrayGeneration_Test r nE width depth n m mu gam
= [ (x',y',z',i,j)
| theta <- [0,2*pi/(nE-1)..2*pi]
, i <- [1..n]
, j <- [1..m]
, let a = width/2
, let b = depth/2
, let x = r * cos(a*cos(theta)/r)
, let y = r * sin(a*cos(theta)/r)
, let z = b * sin(theta)
, let phi = (2*i-1-n)((a-mu)/r)
, let zo = (2*j-1-m)(b-gam)
, let x' = x * cos(phi) - y * sin(phi)
, let y' = x * sin(phi) + y * cos(phi)
, let z' = z + zo
]
But this threw a whole host of errors:
Errors after Type Declaration
Which clearly means I don't know what I'm doing and mucked up the type declarations somehow.
Can anyone steer me the right way?
When you see a compiler error involving something like Num (c -> c), it never has anything to do with -XFlexibleContexts or with incorrect inferred types. It simply means you attempted to use something as a function which is not a function.
“Use as a function” entails simply that you have some expression of the form f x, where f and x can be arbitrary subexpressions. This includes in particular also expressions like (1+2)(3+4), which is the same as
let f = 1 + 2
x = 3 + 4
in f x
Presumably you meant to express multiplication by the juxtaposition. Well, use the multiplication operator then! I.e. (1+2)*(3+4).
Your code has also another problem: you trying to use the index variables in real-valued expression. Unlike the missing multiplication operators, this is fairly sensible, but Haskell doesn't allow this either. You need to explicitly wrap the integrals in fromIntegral.
coilArrayGeneration_Test r nE width depth n m μ γ
= [ (x',y',z',i,j)
| ϑ <- [0, 2*pi/fromIntegral(nE-1) .. 2*pi]
, i <- [1..n]
, j <- [1..m]
, let a = width/2
b = depth/2
x = r * cos(a*cos ϑ/r)
y = r * sin(a*cos ϑ/r)
z = b * sin ϑ
φ = fromIntegral(2*i-1-n) * ((a-μ)/r)
z₀ = fromIntegral(2*j-1-m) * (b-γ)
x' = x * cos φ - y * sin φ
y' = x * sin φ + y * cos φ
z' = z + z₀
]
I would strongly recommend you refactor this a bit, both code and types. 5-tuples are very obscure, you should at least wrap x,y,z in a suitable vector type.

Haskell constants in functions

I was wondering if someone could explain to me what (-2)(-2) in the brackets in the first line of the code stand for. I am new to Haskell and I’m trying to understand.
to_up_left board (x, y, t, c) (-2)(-2) = to_up_left board (x, y, t, c) x y
to_up_left board (x, y, t, c) 0 _ = []
to_up_left board (x, y, t, c) _ 9 = []
to_up_left board ((-1), y, t, c) _ _ = []
to_up_left board (x, y, t, c) _x _y = if (empty_field board (_x-1) (_y+1)) && (t == 'a' || t == 'A' )
then concat [decode_x x ++ decode_y y ++ "-" ++ decode_x (_x-1) ++ decode_y (_y+1)]: to_up_left board (x, y, t, c) (_x-1) (_y+1)
else if (friend_on_field board (_x-1) (_y+1)) && (t == 'a' || t == 'A' )
then concat [decode_x x ++ decode_y y ++ "-" ++ decode_x (_x-1)++ decode_y (_y+1)]: []
else []
if someone could explain to me what (-2) (-2) in the brackets in the first line of the code stand for.
This is to pattern match with negative numbers, otherwise it will be interpreted as
(to_up_left board (x, y, t, c)) - (2 (-2))
and it thus seems that you are defining a (-) function. Negative numbers should thus be specified between parenthesis. The parenthesis have no special meaning: you can nest it an arbitrary number of times ((-2)) for example.
The function to_up_left has 4 arguments. In the top line:
board is the first argument
(x, y, t, c) is the second argument
(-2) is the third argument
(-2) is the fourth argument.
The (-2) arguments need their parentheses because otherwise - would act as a binary operator.
Haskell function definitions do pattern matching:
board names its argument, just as in C-like languages
(x,y,t,c) expects a 4-tuple, and binds the 4 elements to separate names
(-2) checks to see if the argument is equal to -2
if the third and fourth arguments are not both -2, try the next pattern

python dictionary and deque to print required output based on some condition

I have CSV File which contains some data Produced from Mining
I wanted to print it as shown in required format
Required Format
A -> B -> C -> D -> E -> F
A -> B -> C -> I
X -> Y -> Z
X -> Y -> P -> Q
A -> B -> K -> L
a.csv File
## code
from collections import deque
import pandas as pd
data = pd.read_csv("a.csv")
data['Start'] = data['Start'].str.replace(' ','_')
data['End'] = data['End'].str.replace(' ','_')
fronts = dict()
backs = dict()
sequences = []
position_counter = 0
selector = data.apply(lambda row: row.str.extractall("([\w+\d]+)"), axis=1)
for relation in selector:
front, back = relation[0]
llist = deque((front, back))
finb = front in backs.keys()
if finb:
position = backs[front]
llist2 = sequences[position]
back_llist2 = llist2.pop()
llist = llist2 + llist
sequences[position] = llist
backs[llist[-1]] = position
if front in fronts.keys():
del fronts[front]
if back_llist2 in backs.keys():
del backs[back_llist2]
if not finb:
sequences.append(llist)
fronts[front] = position_counter
backs[back] = position_counter
position_counter += 1
data = []
for s in sequences:
data.append(' -> '.join(str(el) for el in s))
data
What I'm Getting is:
'A -> B -> C -> D -> E -> F'
'C -> I'
'A -> N -> A'
'X -> Y -> Z'
'Y -> P -> Q'
'B -> K -> L'
'X1 -> Y1'
You need to search the existing paths for the starting element of the new row. If found, append to the existing path or copy the path and append the new end element.
Try this code:
ss = '''
A B
B C
C D
D E
E F
C I
A N
N A
X Y
Y Z
Y P
P Q
B K
K L
X1 Y1
'''.strip()
lst = []
for r in ss.split('\n'):
lst.append(r.split())
################
paths = []
for e in lst: # each row in source data
pnew = [] # new path
for p in paths:
if e[0] in p: # if start in existing path
if p.index(e[0]) == len(p)-1: # if end of path
p.append(e[1]) # add to path
else:
pnew.append(p[:p.index(e[0])+1]+[e[1]]) # copy path then add
break
else: # loop completed, not found
paths.append(list(e)) # create new path
if len(pnew): # copied path
paths.extend(pnew) # add copied path
print('\n'.join([' => '.join(e) for e in paths]))
Output
A => B => C => D => E => F
A => B => C => I
A => N => A
X => Y => Z
X => Y => P => Q
A => B => K => L
X1 => Y1
The A->N->A and X1->Y1 are correct based on the source data. I don't know why they would be excluded in the desired output.

Is this an accurate example of a Haskell Pullback?

I'm still trying to grasp an intuition of pullbacks (from category theory), limits, and universal properties, and I'm not quite catching their usefulness, so maybe you could help shed some insight on that as well as verifying my trivial example?
The following is intentionally verbose, the pullback should be (p, p1, p2), and (q, q1, q2) is one example of a non-universal object to "test" the pullback against to see if things commute properly.
-- MY DIAGRAM, A -> B <- C
type A = Int
type C = Bool
type B = (A, C)
f :: A -> B
f x = (x, True)
g :: C -> B
g x = (1, x)
-- PULLBACK, (p, p1, p2)
type PL = Int
type PR = Bool
type P = (PL, PR)
p = (1, True) :: P
p1 = fst
p2 = snd
-- (g . p2) p == (f . p1) p
-- TEST CASE
type QL = Int
type QR = Bool
type Q = (QL, QR)
q = (152, False) :: Q
q1 :: Q -> A
q1 = ((+) 1) . fst
q2 :: Q -> C
q2 = ((||) True) . snd
u :: Q -> P
u (_, _) = (1, True)
-- (p2 . u == q2) && (p1 . u = q1)
I was just trying to come up with an example that fit the definition, but it doesn't seem particularly useful. When would I "look for" a pull back, or use one?
I'm not sure Haskell functions are the best context
in which to talk about pull-backs.
The pull-back of A -> B and C -> B can be identified with a subset of A x C,
and subset relationships are not directly expressible in Haskell's
type system. In your specific example the pull-back would be
the single element (1, True) because x = 1 and b = True are
the only values for which f(x) = g(b).
Some good "practical" examples of pull-backs may be found
starting on page 41 of Category Theory for Scientists
by David I. Spivak.
Relational joins are the archetypal example of pull-backs
which occur in computer science. The query:
SELECT ...
FROM A, B
WHERE A.x = B.y
selects pairs of rows (a,b) where a is a row from table A
and b is a row from table B and where some function of a
equals some other function of b. In this case the functions
being pulled back are f(a) = a.x and g(b) = b.y.
Another interesting example of a pullback is type unification in type inference. You get type constraints from several places where a variable is used, and you want to find the tightest unifying constraint. I mention this example in my blog.

Haskell alternative to long list of pattern matches?

I have a function that outputs a booleanlike property given a datatype. This function calculates the property by pattern matching on the first constructor of the datatype, so something like
data C = C1 | C2 | .. | Cn
f :: C -> Bool
f (C1 _ _ ... _) = True
f (C2 _ _ ... _) = True
f (C3 _ _ ... _) = False
.
.
.
f (Cn _ _ ..._) = False
Is there a more compact way to perform pattern-matching, or is there another (also more compact) way to go about my property checking? I prefer not to add the property to the data type definition since it can be calculated with relative ease.
You can avoid the wildcard patterns using record syntax. Also, use a case expression to avoid having to repeat the function name, e.g.
f :: C -> Bool
f x = case x of
C1 {} -> True
C2 {} -> False
...
Cn {} -> False
That's about as compact as it's going to get without changing your data type.
In addition, just list the Trueones or the False ones, depending on what you have less, and make the majority outcome a default:
f C1{} = True
f C42{} = True
f _ = False -- all others false
You might want to look at toConstr in the Data.Data module. This can give you a representation of the constructor, which you can then analyze as you wish (i.e. convert to a String, or get an index out of).
Building on #yatima's answer, you could do something like this
{-# LANGUAGE DeriveDataTypeable #-}
import Data.Char
import Data.Data
data C = C1 Int
| C2 Int
| C3 Int
| C4 Int
deriving (Data,Typeable)
f :: C -> Bool
f c = let [_,n] = show (toConstr c) in digitToInt n < 3
Then in GHCI
>> f (C1 0)
True
>> f (C2 0)
True
>> f (C3 0)
False
>> f (C4 0)
False
Perhaps:
f (x _ _ ... _) = g x where
g C1 = True
g C2 = True
g C3 = False
.
.
.
g Cn = False
You might be able to save a bit of typing using a case statement instead, but not much.
If we had more detail of the problem you were trying to solve (e.g. is there another representation for your data is there some pattern to the output) perhaps there's another approach.

Resources