0

Is there a way to use mutual recursion to create a state machine using existing states.



fun oneElse f xs =
    case xs of
    1::xs' => f xs'
      | [] => true
      | _ => false;
         
fun twoElse xs =
    case xs of
    2::xs' => oneElse twoElse xs'
      | []  => false
      | _ => false

val oneTwo = oneElse twoElse [1,2,1,2];

This is what I have so far, but what I would like is where the higher order function takes these generic (one doesn't know about the next) states.


fun oneElse f xs  = ...
         
fun twoElse f xs = ...


val oneTwo = oneElse (twoElse (oneElse headache) ) xs 

1
  • I would start with writing down the types of these functions and see where that goes. Commented Sep 27, 2021 at 10:32

2 Answers 2

1

You can't do this straightforwardly due to the circularity; oneElse would have the type type of twoElse -> int list -> bool, and twoElse the type type of oneElse -> int list -> bool, so the type of oneElse would be (type of oneElse -> int list -> bool) -> int list -> bool, which expands infinitely.

However, you can solve this using The Standard Solution - add a level of indirection.

datatype Wrap = Wrap of (Wrap -> int list -> bool)

fun oneElse (Wrap f) (1::xs) = f (Wrap oneElse) xs
  | oneElse _ [] = true
  | oneElse _ _ = false


fun twoElse (Wrap f) (2::xs) = f (Wrap twoElse) xs
  | twoElse _ _ = false;

Now both functions have the type Wrap -> int list -> bool, which works out.
You just need to wrap the functions when passing them, and unwrap before applying them.

Test:

- oneElse (Wrap twoElse) [1,2,1,2];
val it = true : bool

- oneElse (Wrap twoElse) [1,2,1];
val it = false : bool
Sign up to request clarification or add additional context in comments.

Comments

0

Currently the definition of oneElse and twoElse are not mutually recursive. And to be able to establish mutuality we must have oneElse making use of twoElse and vice-versa.

Unsure of whether it will achieve what is intended or not... one way would be to define both functions following way, exhibiting mutual recursion:

fun oneElse xs =
    case xs of
        1::xs' => twoElse xs'
      | [] => true
      | _ => false
and twoElse xs =
    case xs of
        2::xs' => oneElse xs'
      | []  => false
      | _ => false;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.