Jak podać jawne deklaracje typu dla funkcji podczas korzystania z GHCi?

82

Jak zdefiniować odpowiednik tej funkcji (wzięty z learnyouahaskell ) w GHCi?

import Data.List  

numUniques :: (Eq a) => [a] -> Int  
numUniques = length . nub  

Bez deklaracji typu GHCi akceptuje definicję funkcji, ale kończy się niepomocnym typem:

Prelude Data.List> import Data.List 
Prelude Data.List> let numUniques' = length . nub
Prelude Data.List> :t numUniques'
numUniques' :: [()] -> Int

Wynikowa funkcja akceptuje tylko listę jednostek jako parametr.

Czy istnieje sposób zapewnienia deklaracji typu w GHCi? A może istnieje inny sposób definiowania takich funkcji, które nie wymagają deklaracji typu?

Nie widziałem żadnych oczywistych wskazówek w przewodniku po GHCi i eksperymentowałem z wyrażeniami takimi jak następujące (bezskutecznie):

> let numUniques' = ((length . nub) :: (Eq a) => [a] -> Int)
> :t numUniques'
numUniques' :: [()] -> Int
mattbh
źródło

Odpowiedzi:

101

Czy istnieje sposób zapewnienia deklaracji typu w GHCi?

let numUniques' :: (Eq a) => [a] -> Int; numUniques' = length . nub

A może istnieje inny sposób definiowania takich funkcji, które nie wymagają deklaracji typu?

Jeśli wyłączysz ograniczenie monomorfizmu za pomocą -XNoMonomorphismRestriction, wywnioskuje on właściwy typ.

sepp2k
źródło
3
Nie jestem jeszcze tam z monomorfizmem, ale generalnie ta odpowiedź wskazywała mi na używanie średników do grupowania definicji w GHCi - tutoriale są pisane jak w pliku .hs, co daje wiele różnych problemów, gdy próbuję w GHCi (funkcje nie są powiązane itp. .).
Tomasz Gandor
Warto zauważyć, że -XNoMonomorphismRestrictionjest on domyślnie włączony dla GHCi od 7.8.1: downloads.haskell.org/~ghc/latest/docs/html/users_guide/ ...
N. Shead
13

Zauważ, że możesz również uniknąć ograniczenia monomorfizmu, po prostu dodając „punkty” (tj. Zmienne jawne) z powrotem do wyrażenia. Więc to również daje właściwy typ:

niech numUniques x = długość. nub $ x

sclv
źródło
1
Dzięki - świetnie wiedzieć.
mattbh
Jest to znane jako rozszerzenie eta
Bladt
3

Przewodnik użytkownika GHC przedstawia dwa dodatkowe sposoby osiągnięcia tego celu. Ta podsekcja wprowadza konstrukcję :{... :}, której można użyć w następujący sposób:

> :{
| numUniques :: (Eq a) => [a] -> Int
| numUniques = length . nub
| :}

Alternatywnie możesz włączyć tryb wielowierszowy :

> :set +m
> let
| numUniques :: (Eq a) => [a] -> Int
| numUniques = length . nub
| 
Reinier Torenbeek
źródło