Как сочинить 'не' с функцией произвольной арности?

31
задан Miles Rout 4 May 2015 в 06:24
поделиться

4 ответа

Если Вы не хотите пойти, бездельничая с typeclasses, который лучше оставлен для мысленных экспериментов и подтверждения концепции, Вы просто не делаете вывод к нескольким аргументам. Не пробовать.

Что касается Вашего основного вопроса, это наиболее изящно решено с Conal Elliott семантический редактор combinators . Семантический редактор combinator является функцией с типом как:

(a -> b) -> F(a) -> F(b)

, Где F(x) некоторое выражение, включающее x. Существует также "контравариантный" редактор combinators, которые берут (b -> a) вместо этого. Интуитивно, редактор combinator выбирает часть некоторого большего значения для работы на. Тот, в котором Вы нуждаетесь, называют result:

result = (.)

Взгляд на тип выражения Вы пытаетесь воздействовать на:

a -> a -> Bool

результат (область изменения) этого типа a -> Bool, и результат [1 121], что тип Bool, и это - то, к чему Вы пытаетесь подать заявку not. Таким образом для применения not к результату результата функции f Вы пишете:

(result.result) not f

Это красиво делает вывод. Вот являются еще много combinators:

argument = flip (.)     -- contravariant

first f (a,b) = (f a, b)
second f (a,b) = (a, f b)

left f (Left x) = Left (f x)
left f (Right x) = Right x
...

Поэтому, если у Вас есть значение x из типа:

Int -> Either (String -> (Int, Bool)) [Int]

И Вы хотите подать заявку not к Bool, Вы просто обстоятельно объясняете путь для получения там:

(result.left.result.second) not x

, О, и если Вы добрались до Функторов уже, Вы заметите, что fmap редактор combinator. На самом деле вышеупомянутое может быть записано:

(fmap.left.fmap.fmap) not x

, Но я думаю, что это более ясно использовать расширенные имена.

Обладают.

41
ответ дан 27 November 2019 в 21:31
поделиться

На самом деле выполнение произвольной арности с классами типа оказывается невероятно легким:

module Pred where

class Predicate a where
  complement :: a -> a

instance Predicate Bool where
  complement = not

instance (Predicate b) => Predicate (a -> b) where
  complement f = \a -> complement (f a)  
  -- if you want to be mysterious, then
  -- complement = (complement .)
  -- also works

ge :: Ord a => a -> a -> Bool
ge = complement (<)

спасибо за указание на эту прохладную проблему. Я люблю Haskell.

41
ответ дан 27 November 2019 в 21:31
поделиться

Ваш n combinator может быть записан:

n = ((not .) .)

Что касается Вашего вопроса о премии, типичный путь вокруг состоял бы в том, чтобы создать несколько из них:

lift2 = (.).(.)
lift3 = (.).(.).(.)
lift4 = (.).(.).(.).(.)
lift5 = (.).(.).(.).(.).(.)

и т.д.

12
ответ дан 27 November 2019 в 21:31
поделиться

Ре: , Что я делаю неправильно? :

я думаю, что Ваш combinator прекрасен, но когда Вы позволяете - связывают его на верхнем уровне, одно из раздражающих 'правил Haskell по умолчанию' начинает действовать, и привязка не обобщена:

Prelude> :ty (n f)
(n f) :: (Ord t) => t -> t -> Bool
Prelude> let g = n f
Prelude> :ty g
g :: () -> () -> Bool

я думаю, что можно становиться ударенными 'ограничением мономорфизма', поскольку оно применяется к классам типа. В любом случае, если Вы выходите из цикла верхнего уровня и помещаете вещи в отдельный файл с явной подписью типа, все это хорошо работает:

module X where

n f = (\a -> \b -> not $ f a b)
f a b = a > b

g :: Ord a => a -> a -> Bool
g = n f

вопрос о Премии : чтобы сделать это со все большим количеством параметров типа, можно попытаться играть приемы цинги с системой классов типа. Двумя бумагами для консалтинга является Hughes и Claessen статья о QuickCheck и статья Ralf Hinze Дженерики для Масс .

9
ответ дан 27 November 2019 в 21:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: