Como compor `não` com uma function de aridade arbitrária?

Quando eu tenho alguma function do tipo

f :: (Ord a) => a -> a -> Bool fab = a > b 

Eu gostaria de fazer function que envolva essa function com não.

por exemplo, fazer function como esta

 g :: (Ord a) => a -> a -> Bool gab = not $ fab 

Eu posso fazer combinator como

 nf = (\a -> \b -> not $ fab) 

Mas eu não sei como.

 *Main> let nf = (\a -> \b -> not $ fab) n :: (t -> t1 -> Bool) -> t -> t1 -> Bool Main> :tnf nf :: (Ord t) => t -> t -> Bool *Main> let g = nf g :: () -> () -> Bool 

O que estou fazendo de errado?

E bônus pergunta como eu posso fazer isso para funcionar com mais e menos de parâmetros, por exemplo

 t -> Bool t -> t1 -> Bool t -> t1 -> t2 -> Bool t -> t1 -> t2 -> t3 -> Bool 

A menos que você queira fazer hacking com typeclasss, o que é melhor deixar para experiências de pensamento e prova de conceito, você simplesmente não generaliza para múltiplos argumentos. Não tente.

Quanto à sua questão principal, isso é mais elegantemente resolvido com os combinadores de editor semântico de Conal Elliott. Um combinador de editor semântico é uma function com um tipo como:

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

Onde F(x) é alguma expressão envolvendo x . Há também combinadores de edição “contravariantes” que tomam um (b -> a) . Intuitivamente, um combinador de editor seleciona uma parte de algum valor maior para operar. O que você precisa é chamado de result :

 result = (.) 

Veja o tipo de expressão que você está tentando usar:

 a -> a -> Bool 

O resultado (codomain) desse tipo é a -> Bool , e o resultado desse tipo é Bool , e é isso que você está tentando aplicar not . Então, para aplicar not ao resultado do resultado de uma function f , você escreve:

 (result.result) not f 

Isso generaliza lindamente. Aqui estão mais alguns combinadores:

 argument = flip (.) -- contravariant first f (a,b) = (fa, b) second f (a,b) = (a, fb) left f (Left x) = Left (fx) left f (Right x) = Right x ... 

Então, se você tem um valor x do tipo:

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

E você quer se inscrever not no Bool, você apenas soletra o caminho para chegar lá:

 (result.left.result.second) not x 

Ah, e se você chegou ao Functors ainda, você notará que o fmap é um combinador de editor. Na verdade, o acima pode ser escrito:

 (fmap.left.fmap.fmap) not x 

Mas acho que é mais claro usar os nomes expandidos.

Apreciar.

Na verdade, fazer arty arbitrário com classs de tipos é incrivelmente fácil:

 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 (fa) -- if you want to be mysterious, then -- complement = (complement .) -- also works ge :: Ord a => a -> a -> Bool ge = complement (<) 

Obrigado por apontar este problema legal. Eu amo o Haskell.

Seu n combinador pode ser escrito:

 n = ((not .) .) 

Quanto à sua pergunta de bônus, a maneira típica seria criar várias delas:

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

etc.

Re: O que estou fazendo de errado? :

Eu acho que seu combinador é bom, mas quando você o liga no nível mais alto, uma das “regras padrão” irritantes de Haskell entra em jogo e a binding não é generalizada:

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

Eu acho que você pode estar sendo derrotado pela ‘restrição de monomorfismo’ como se aplica às classs de tipos. Em qualquer caso, se você sair do loop de nível superior e colocar as coisas em um arquivo separado com uma assinatura de tipo explícito, tudo funcionará bem:

 module X where nf = (\a -> \b -> not $ fab) fab = a > b g :: Ord a => a -> a -> Bool g = nf 

Pergunta bônus : para fazer isso com mais e mais parâmetros de tipo, você pode tentar jogar truques de escorbuto com o sistema de class de tipos. Dois artigos a serem consultados são o artigo de Hughes e Claessen sobre o QuickCheck e o artigo de Ralf Hinze, Generics for the Masses .

Intereting Posts