2015-10-07 2 views
3

при попытке написать простую программу для решения проблемы SAT игрушки, я столкнулся со следующей проблемой: я не могу опустить голову.Ocaml оценивает булевский список на один логический

У меня есть переменная типа, которая определяется следующим образом:

type prefix = 
    | Not 
    | None 

type variable = 
    | Fixed of (prefix * bool) 
    | Free of (prefix * string) 

, из которого можно построить раздел списка переменных типа и формулу списка п типа. По существу это сводится к тому, чтобы иметь формулу в либо CNF, либо DNF (это меньше связано с проблемой). Когда сейчас пытается упростить положение, что я делаю следующее:

  • Фильтр всех фиксированных переменных из положения, которое дает список
  • упрощать переменные (Fixed (нет, правда) => Fixed (None, ложь))

Теперь у меня есть список, содержащий только Фиксированные переменные, которые я теперь хочу, чтобы объединить в одно фиксированное значение, делая что-то вроде этого

let combine l = 
    match l with 
    | [] -> [] 
    | [x] -> [x] 
    | (* Get the first two variables, OR/AND them 
     and recurse on the rest of the list *) 

Как мне достичь желаемого поведения на функциональном языке? Мой опыт в OCaml не такой уж большой, я скорее начинающий. Я пробовал делать x :: xs :: rest -> x < ||> xs < ||> комбинировать отдых, но это не работает. Где < ||> является обычным оператором для ИЛИ переменных.

Благодарим за помощь.

ответ

1

Вот моя попытка:

let rec combine l = 
    match l with 
    | [] -> [] 
    | [x] -> [x] 
    | a :: b :: rest -> combine ((a <||> b) :: rest) 

Примечание вам нужно let rec.

2

Как насчет того, чтобы использовать аккуратные функции более высокого порядка уже там?

let combine = function 
    | x::xs -> List.fold_left (<||>) x xs 
    | [] -> failwith "darn, what do I do if the list is empty?" 

Для уточнения:

List.fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a 

принимает функцию которая получает работает совокупный и следующий элемент списка; он возвращает новый агрегат; то нам нужно начальное значение и список элементов, которые нужно сложить. Использование вашего оператора infix <||> в скобках делает его префиксом, поэтому мы можем присвоить его List.fold_left именно так - вместо того, чтобы писать (fun a b -> a <||> b).

Если у вас есть нейтральный элемент вашего оператора <||>, позволяет называть его one, мы могли бы написать его еще более кратким:

let combine = List.fold_left (<||>) one 

Как List.fold_left требует три аргумента, и мы только дали ему два, combine здесь функция от variable list -> variable как предыдущая. Если вам интересно, почему это работает, ознакомьтесь с концепцией currying.

Смежные вопросы