Pre-Script
... And just when I finished producing these example, I saw the 'roundtrip' flow topic, which looks nice.
Since I've already put this on here, might as well ask: are there another alternatives?
Original Post
Is there a way to automatically lay out nodes in a rectangular layout when in a subgraph?
As an example, say I have the given structure:
digraph
{
rankdir="LR";
node [ shape="circle", style="bold, filled", fillcolor="#dddddd" ];
a -> b -> c -> d -> e -> f -> g -> h -> b;
}
This yields the diagram
My goal is to have them line up in a rectangle with rows of three nodes, forming
If I try to constrain the rank and change the rankdir, it is not as expected (I'm assuming because you can't change rankdir like this):
digraph
{
rankdir="LR";
node [ shape="circle", style="bold, filled", fillcolor="#dddddd" ];
a -> b -> c -> d -> e -> f -> g -> h -> b;
subgraph
{
rankdir="TB";
rank="same";
c; d; e;
}
subgraph
{
rankdir="TB";
rank="same";
f; g; h;
}
}
If I go through and manually and assign rank to line up as I desired, it works:
digraph
{
rankdir="LR";
node [ shape="circle", style="bold, filled", fillcolor="#dddddd" ];
a -> b -> c -> d -> e -> f -> g -> h -> b;
{ rank="same"; c; h; }
{ rank="same"; d; g; }
{ rank="same"; e; f; }
}
Edit
Just tried out the method, worked well. I did have to unconstrain the right-most edge to prevent it from making an asymetric shape, but overall worked like a charm (and much more intuitive)!
digraph
{
rankdir="LR";
node [ shape="circle", style="bold, filled", fillcolor="#dddddd" ];
a -> b -> c -> d -> e;
e -> f [ constraint="false" ];
b -> h -> g -> f [ dir="back" ];
}
Not sure where to put this, but I will go ahead and post it here as a side answer.
I tried out a larger cycle:
digraph
{
rankdir="LR";
node [ shape="circle", style="bold, filled", fillcolor="#dddddd" ];
x -> y;
y -> aa [ constraint="false" ];
aa -> ab -> ac -> ba;
{ rank="same"; ba -> bb -> bc -> ca; }
da -> cc -> cb -> ca [ dir="back" ];
{ rank="same"; aa -> dc -> db -> da [ dir="back" ]; };
}
Also tried out a serpentine pattern:
digraph
{
rankdir="LR";
node [ shape="circle", style="bold, filled", fillcolor="#dddddd" ];
x -> y;
y -> aa [ constraint="false" ];
aa -> ab -> ac;
ac -> ba [ constraint="false" ];
bc -> bb -> ba [ dir="back" ];
bc -> ca [ constraint="false" ];
ca -> cb -> cc;
cc -> da [ constraint="false" ];
dc -> db -> da [ dir="back" ];
y -> dc [ dir="back", constraint="false" ];
// { rank="same"; aa; bc; ca; dc; };
}
This one's still a bit messy.
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
Today I have a new problem with another code in Haskell: I get the following error "parse error on input `<-'". Would someone explain to me what is wrong with the code and how to make it right? Thanks!
f :: (Int,Int) -> (Int,Int) -> Int -> Int -> [[Int]]
f (h, w) (a, b) k l = let x <- [1..w]
y <- [1..h]
zahl1 <- [1..k]
zahl2 <- [1..l]
in [if ((y, x) == (a, b)) then zahl1 else zahl2] ```
The left arrow (<-) is used to assign values inside do notation, like this:
main = do
line <- getLine
print line
The equals sign is used to assign values as part of a let ... in ... expression, like this:
main =
let line = "hello"
in print line
So mechanically you might think to replace <- with =, but that wouldn't work for your case. It looks like you're trying to create a list using a list comprehension, but instead you're creating a list with only one value in it. I think this may be what you're trying to do:
f :: ( Int, Int ) -> ( Int, Int ) -> Int -> Int -> [ [ Int ] ]
f ( h, w ) ( a, b ) k l =
let
zahl1 = [ 1 .. k ]
zahl2 = [ 1 .. l ]
in
[ if ( y, x ) == ( a, b ) then zahl1 else zahl2
| x <- [ 1 .. w ]
, y <- [ 1 .. h ]
]
I wouldn't necessarily recommend this, but as a bit of trivia you can write list comprehensions using do notation:
f ( h, w ) ( a, b ) k l = do
x <- [ 1 .. w ]
y <- [ 1 .. h ]
if ( y, x ) == ( a, b )
then [ 1 .. k ]
else [ 1 .. l ]
This question already has an answer here:
Is it possible to automatically implement a trait for any tuple that is made up of types that all implement the trait?
(1 answer)
Closed 3 years ago.
I have a trait like this:
trait Foo {
fn do_something(self) -> Self;
}
And I want implement this trait for a tuple that may have any number of elements that implement this trait.
impl<T> Foo for (T, T) where T: Foo {
fn do_something(self) -> Self {
let (t0, t1) = self;
(t0.do_something(), t1.do_something())
}
}
impl<T> Foo for (T, T, T) where T: Foo {
fn do_something(self) -> Self {
let (t0, t1, t2) = self;
(t0.do_something(), t1.do_something(), t2.do_something())
}
}
// and so on...
Note: I'm not sure whether you should do this, but here's a way to anyway. (Feels hacky to me, and that may be because I don't know how to make a better macro.)
Homogeneous tuples (T, T)
The way you've described it:
impl<T> Foo for (T, T) where T: Foo
Here, the entire tuple must be homogeneous (i.e. (MyType, MyType2).do_something() will not work because of monomorphization).
This raises a flag because tuples are for heterogeneous data.
If implementing the trait only one homogeneous tuples is still what you want, we can implement a macro the way the standard library does to implement traits for varied length tuples, with some modifications. (Click src on the right of an impl to see it's source.)
macro_rules! replace_expr {
($_t:tt $sub:ty) => {$sub};
}
macro_rules! tuple_impls {
( $( $name:ident )+ ) => {
impl<T: Foo> Foo for ($(replace_expr!(($name) T),)+)
{
fn do_something(self) -> Self {
let ($($name,)+) = self;
($($name.do_something(),)+)
}
}
};
}
tuple_impls! { A }
tuple_impls! { A B }
tuple_impls! { A B C }
tuple_impls! { A B C D }
tuple_impls! { A B C D E }
tuple_impls! { A B C D E F }
tuple_impls! { A B C D E F G }
tuple_impls! { A B C D E F G H }
tuple_impls! { A B C D E F G H I }
tuple_impls! { A B C D E F G H I J }
tuple_impls! { A B C D E F G H I J K }
tuple_impls! { A B C D E F G H I J K L }
Playground
Heterogeneous tuples (T1, T2)
If you're okay with (MyType, MyType2).do_something() working (where both implement the Foo trait), you can try this simpler macro:
macro_rules! tuple_impls {
( $( $name:ident )+ ) => {
impl<$($name: Foo),+> Foo for ($($name,)+)
{
fn do_something(self) -> Self {
let ($($name,)+) = self;
($($name.do_something(),)+)
}
}
};
}
tuple_impls! { A }
tuple_impls! { A B }
tuple_impls! { A B C }
tuple_impls! { A B C D }
tuple_impls! { A B C D E }
tuple_impls! { A B C D E F }
tuple_impls! { A B C D E F G }
tuple_impls! { A B C D E F G H }
tuple_impls! { A B C D E F G H I }
tuple_impls! { A B C D E F G H I J }
tuple_impls! { A B C D E F G H I J K }
tuple_impls! { A B C D E F G H I J K L }
Playground
No. (unless you are ready to use macros - see other answers)
Tuples in Rust have a fixed length just like arrays. I do not believe you can express the concept of "tuples of any length".
In other words a tuple of 2 elements is a different compound type than a tuple of 3 elements. If you insist on using tuples you have to go for the solution you outlined above.
Use a collection? (such as aliasing an existing one and implementing the trait on it)?
f0 :: Int -> Int -> Int -> Int
f0 a b c = x a b - x a c - x b c
where x b a = a + b
Can someone explain me how the functions knows what to do when it gets to the...
where x b a = a + b
... statement? Does it just translate to something like this?
f0 a b c = (a + b) a b - (a + b) a c - (a + b) b c
[...] or is it just that the "x" is just another functions which takes two variables and add them [...]
Exactly. x b a = a + b is a function definition (that happens to have local scope). f0 0 0 1 = x 0 0 - x 0 1 - x 0 1. – duplode
In some other pseudo language this will look like this.
int function fo(int a, int b, int c){
int function x(int a, int b){
return a + b;
}
return x(a,b) - x(a,c) - x(b,c)
}
The way you have put it as a question,
f0 a b c = (a + b) a b - (a + b) a c - (a + b) b c
it looks like inline substitution like C macros. It is not simple code substitution. It is more like inline function. X is a function which gets called.
If I create the following multi-line string literal:
let lit = "A -> B
C -> D
E -> F";
It prints out like this:
A -> B
C -> D
E -> F
No surprise. However, if I try this:
let lit = "A -> B\
C -> D\
E -> F";
I get:
A -> BC -> DE -> F
What I'm trying to get is this:
A -> B
C -> D
E -> F
But this is the best thing I've come up with:
let lit = "A -> B\n\
C -> D\n\
E -> F";
Or maybe this:
let lit = vec!["A -> B", "C -> D", "E -> F"].connect("\n");
Both of those feel a little clunky, though not terrible. Just wondering if there's any cleaner way?
Indoc is a procedural macro that does what you want. It stands for "indented document." It provides a macro called indoc!() that takes a multiline string literal and un-indents it so the leftmost non-space character is in the first column.
let lit = indoc! {"
A -> B
C -> D
E -> F"
};
The result is "A -> B\nC -> D\nE -> F" as you asked for.
Whitespace is preserved relative to the leftmost non-space character in the document, so the following preserves 2 spaces before "C":
let lit = indoc! {"
A -> B
C -> D
E -> F"
};
The result is "A -> B\n C -> D\nE -> F".
I see three other possible solutions:
1) Get rid of the spaces:
let lit = "A -> B
C -> D
E -> F";
This way, you lose the neat display in your code. You could get that back like this:
2) Get rid of the spaces, shift everything down a line, and escape the return.
let lit = "\
A -> B
C -> D
E -> F";
I would explain what that "\" is doing in a comment, though, because it isn't obvious otherwise.
3) Combine these two solutions:
let lit =
"A -> B
C -> D
E -> F";
You can test this at Ideone.
Mostly as an exercise, I mimicked Python's join syntax with the following:
trait CanJoin {
fn join(&self, in_strings: Vec<&str>) -> String;
}
impl CanJoin for str {
fn join(&self, in_strings: Vec<&str>) -> String {
in_strings.connect(self)
}
}
fn main() {
let vector = vec!["A -> B", "B -> C", "C -> D"];
let joined = "\n".join(vector);
}
Or as a macro:
macro_rules! join_lines {
($($x:tt)*) => {
{
vec![$($x)*].connect("\n")
}
}
}
let joined = join_lines!("A -> B", "B -> C", "C -> D");
Suppose there is a type r = {A : int; B : string; C : int; D : string} and a some values:
let aOptional : int option = ...
let bOptional : string option = ...
let cOptional : int option = ...
let dOptional : string option = ...
How can r optional could be constructed from them eleganlty (without nested case-stuff, etc.)?
Btw, here is how it could be done in haskell with Control.Applicative:
data R = R { a :: Integer, b :: String, c :: Integer, d :: String}
R <$> aOptional <*> bOptional <*> cOptional <*> dOptional :: Maybe R
Looking for something equivalent in fsharp.
The only way I know (using applicatives) is by creating a function to construct the record:
let r a b c d = {A = a; B = b; C = c; D = d}
Then you can do:
> r </map/> aOptional <*> bOptional <*> cOptional <*> dOptional ;;
val it : R option
You can define map and <*> yourself, but if you want a generic implementation try that code with F#+ or if you want to use FsControl directly you can write the code this way:
#r "FsControl.Core.dll"
open FsControl.Operators
let (</) = (|>)
let (/>) f x y = f y x
// Sample code
type R = {A : int; B : string; C : int; D : string}
let r a b c d = {A = a; B = b; C = c; D = d}
let aOptional = Some 0
let bOptional = Some ""
let cOptional = Some 1
let dOptional = Some "some string"
r </map/> aOptional <*> bOptional <*> cOptional <*> dOptional
// val it : R option = Some {A = 0; B = ""; C = 1; D = "some string";}
UPDATE: Nuget packages are available now.
The straightforward way is:
match aOptional, bOptional, cOptional, dOptional with
| Some a, Some b, Some c, Some d -> Some {A=a; B=b; C=c; D=d}
| _ -> None
or, with a maybe monad:
let rOptional =
maybe {
let! a = aOptional
let! b = bOptional
let! c = cOptional
let! d = dOptional
return {A=a; B=b; C=c; D=d}
}