Domanda

È possibile scrivere una funzione arity :: a -> Integer per determinare l'aria delle funzioni arbitrarie, tale che

> arity map
2
> arity foldr
3
> arity id
1
> arity "hello"
0

?

È stato utile?

Soluzione

È facile con OverlappingInstances:

{-# LANGUAGE FlexibleInstances, OverlappingInstances #-}

class Arity f where
  arity :: f -> Int

instance Arity x where
  arity _ = 0

instance Arity f => Arity ((->) a f) where
  arity f = 1 + arity (f undefined) 

Aggiorna Problema trovato. È necessario specificare il tipo non polimorfico per le funzioni polimorfiche:

arity (foldr :: (a -> Int -> Int) -> Int -> [a] -> Int)

Non so ancora come risolverlo.

Up up Come ha commentato Sjoerd Visscher di seguito "devi specificare un tipo non polimorfico, poiché la risposta dipende dal tipo che scegli".

Altri suggerimenti

Sì, può essere fatto molto, molto facilmente:

arity :: (a -> b) -> Int
arity = const 1

Razionale: se è una funzione, puoi applicarlo esattamente a 1 argomento. Si noti che la sintassi di Haskell rende impossibile applicare a 0, 2 o più argomenti come f a b è davvero (f a) b, cioè no f applied to a and b, ma (f applied to a) applied to b. Il risultato può, ovviamente, essere un'altra funzione che può essere nuovamente applicata e così via.

Sembra stupido, ma non è altro che la verità.

Se id ha Arity 1, non dovrebbe id x Hai Arity 0? Ma, per esempio, id map è identico a map, che avrebbe Arity 2 nel tuo esempio.

Le seguenti funzioni hanno la stessa Arity?

f1 = (+)
f2 = (\x y -> x + y)
f3 x y = x + y

Penso che la tua nozione di "arity" non sia ben definita ...

In Haskell, ogni "funzione" prende esattamente un argomento. Quella che sembra una funzione "multi-argomentazione" è in realtà una funzione che prende un argomento e restituisce un'altra funzione che prende il resto degli argomenti. Quindi in questo senso tutte le funzioni hanno Arity 1.

Non è possibile con Haskell standard. Potrebbe essere possibile utilizzando le incoerenttinstance o l'estensione simile.

Ma perché vuoi farlo? Non puoi chiedere a una funzione quanti argomenti si aspetta e quindi utilizzare questa conoscenza per dargli esattamente quel numero di argomenti. (A meno che tu non stia usando template Haskell, nel qual caso, sì, mi aspetto che sia possibile al momento della compilazione. Stai usando il modello Haskell?)

Qual è il tuo vero problema che stai cercando di risolvere?

Cosa ne pensi di questo:

arity :: a -> Int
arity (b->c) = 1 + arity (c)
arity _ = 0
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top