2015-07-19 30 views
10

ben daktilo ve bir hata olduğunu aşağıdaki>Garip Haskell ifadesi ([Char] -> t) GHCi bazı egzersizleri yaparken => t

ghci> (1 "one") 

<interactive>:187:1: 
    No instance for (Num ([Char] -> a0)) arising from a use of ‘it’ 
    In a stmt of an interactive GHCi command: print it 

var howeve ben GHCi sorarsanız

ghci> :type (1 "one") 
(1 "one") :: Num ([Char] -> t) => t 

(1 "one") anlamı nedir: ifade türü için herhangi bir hata vermez?

Bu ifade neden bir hata veriyor, ancak GHCi iyi yazıldığını söylüyor?

Num ([Char] -> t) => t nedir?

Teşekkürler.

+1

Alanın işlev uygulama operatörü olduğunu unutmayın. – Bergi

cevap

10

Haskell Rescue'ye bildirin!

Prelude> :t fromInteger 
fromInteger :: Num a => Integer -> a 

Yani 1 aslında fromInteger (1 :: Integer) sözdizimi şeker:

An integer literal represents the application of the function fromInteger to the appropriate value of type Integer.

fromInteger tip vardır (section 6.4.1 aktaran). Sizin ifade halde, geçerli:

fromInteger 1 "one" 
olarak yazılmış olabilir

: Artık

(fromInteger 1) "one" 

, fromInteger bir numara (bu kadar, Num bir örneği olup, bir türde bir değerdir üretir onun türü bize söyler). İfadenizde bu sayı [Char] ("one" dizgisi) için geçerlidir. olduğu

Num ([Char] -> t) => t 

, sonucun olacağını da [Char] bir Num olan bir işlevi uygulanması (belirtilmemiş tip t arasında): GHC doğru ifadesi yazın sahip olduğunu anlamak için bilginin bu iki eseri eşliğinde. Bu prensipte geçerli bir tiptir. Tek sorun, [Char] -> t için Num örneğinin olmamasıdır (yani, dizeleri alan işlevler sayı değil, bu şaşırtıcı değildir).

S.S .: Sibi ve Ørjan'ın belirttiği gibi, GHC 7.10 ve sonrasında sadece FlexibleContexts GHC uzantısının etkin olup olmadığı sorusunda bahsedilen hatayı göreceksiniz; Aksi takdirde, tip denetçisi, sınıf kısıtlaması içinde sabit tipler ve tip yapıcıların bulunmasından şikayet eder (yani, Char, [] ve (->)).

+1

İyi cevap. Ayrıca, 'ghci'de heceleme yapmak isterseniz,' FlexibleContexts' bağlamları eklentisini etkinleştirerek yapılabilir. 'x = 1 'bir' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ' – Sibi

+0

Sorunun, 'FlexibleContexts' GHC uzantısının etkinleştirildiğini varsaydığını sanmıyorum. ': T (1" one ") türü, ghci IMO'nun tutarlı bir davranışı olmayan uzantıyı etkinleştirmeden çalışır. – Sibi

+0

@Sibi Gerçekten. Yine de, 'FlexibleContexts' özelliğini etkinleştirmezseniz ': t' olmayan hatayı değiştirir. – duplode

1

TL; DR: Bitmiş endişeli elde değmez bir bozuk saçma bir tip.

tamsayı sabitleri Num typeclass uygulayan her tür değerleri temsil edebilir. Yani 1 veya başka bir tam sayı literal bir sayıya ihtiyacınız olan her yerde kullanılabilir.

doubleVal :: Double 
doubleVal = 1 

intVal :: Int 
intVal = 1 

integerVal :: Integer 
integerVal = 1 

Bu, herhangi bir sayısal bağlamda tümleşik değişmezleri esnek bir şekilde kullanabilmemizi sağlar.

Herhangi bir tür bağlamı olmayan bir tamsayı hazırladığınızda, ghci ne tür olduğunu bilmiyor.

Prelude> :type 1 
1 :: Num a => a 

GHCi " '1' Bilmiyorum bir tür olduğunu, ama ne olursa olsun tipi, yani tip Num typeclass uygulayan biliyorum" diyor.

Haskell kaynağındaki bir tamsayı değişkeni her oluşumu, örtülü bir fromInteger işleviyle sarılır. Bu nedenle (1 "one") dolaylı olarak ((fromInteger (1::Integer)) "one")'a dönüştürülür ve (fromInteger (1::Integer)) alt ifadesi, henüz bilinmeyen bir tür olan Num a => a türünde henüz bilinmeyen bir türe sahiptir, ancak bunun Num yazım tipinin bir örneğini sağladığını biliyoruz.

Biz de "one" bir işlev gibi uygulandığını görebilirsiniz, bu yüzden onun tip a0 henüz başka bilinmeyen bir türüdür formunu [Char] -> a0 olması gerektiğini biliyoruz. Yani a ve [Char] -> a0 aynı olmalıdır. Yukarıda anladığımız Num a => a türüne dönerek, 1'un Num ([Char] -> a0) => [Char] -> a0) türünde olması gerektiğini ve (1 "one") ifadesinin Num ([Char] -> a0) => a0 türünde olduğunu biliyoruz. "Orada bir işleve bir [Char] argüman uygulanması sonucunda elde edilir bazı tip a0 olduğunu ve fonksiyon tipi Num sınıfının bir örneğidir olarak bu son türünü okuyun.

Yani ifadesinin kendisi geçerli bir tür Num ([Char] -> a0) => a0 sahiptir.

Haskell, Monomorphism restriction adlı bir şeye sahiptir.Bunun bir yönü, ifadelerdeki tüm tip değişkenlerinin, bunları değerlendirebilmeniz için belirli, bilinen bir türe sahip olması gerektiğidir.GSC, bazı durumlarda, varsayılan duruma getirme kurallarını kullanır. Monomorfizm kısıtlaması Ancak, GHC herhangi bir tip a0 bilmiyor, yukarıda tanımlanmış bir Num örneğine sahip olan tip ifadesine takılabilir. t ile başa çıkmak için bir yolu yoktur ve "Num için No Örneği" iletisini verir.

+1

Kesinlikle * değil * 'bozuk saçmalık tipi'. Neden böyle diyorsun? – AJFarmar

+0

Türü yararlı ve anlamlı olarak değerlendiriyor musunuz? – NovaDenizen

+0

@NovaDenizen Evet! Örneğin, cevabımı buradan görebilirsiniz - http://stackoverflow.com/questions/32443925/haskell-weird-expression/32444024#32444024 –

3

Haskell, oldukça esnek bir dildir, ancak aynı zamanda çok tam anlamıyla bir mantıksal biridir. Çoğu zaman, çoğu dilde yazılan şeyler sadece sözdizimi hataları olurken, Haskell onlara bakacak ve onları anlamak için onun en sevdiği şeyleri deneyecek, gerçekten kafa karıştırıcı olan ancak gerçekten de dil kurallarının mantıksal sonuçları olan sonuçlarla. Biz Python içine örnek yazarsanız

, temelde "ne sadece yazdığınız sıfır mantıklı" söyler:

irb(main):001:0> (1 "one") 
SyntaxError: (irb):1: syntax error, unexpected tSTRING_BEG, expecting ')' 
(1 "one") 
    ^
    from /usr/bin/irb:12:in `<main>' 

:

Python 2.7.6 (default, Sep 9 2014, 15:04:36) 
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> (1 "one") 
    File "<stdin>", line 1 
    (1 "one") 
     ^
SyntaxError: invalid syntax 

Yakut aynı şeyi yapar Ama Haskell bu kadar kolay pes etmiyor! xa tip vardır ve f xb tip vardır, a -> b gibi yazın nerede f,

formun f x ait
  • İfadeler fonksiyon uygulamaları şunlardır: Bu (1 "one") görür ve bu müzakere eder.
  • 1 "one", 1 ifadesinde, bağımsız değişken olarak "one" ([Char]) alan bir işlev olmalıdır. Sonra sayısal değişmezleri arasında Haskell'ın tedavi verilen

, bu fromInteger 1 :: Num b => [Char] -> b içine 1 çevirir. fromInteger, Num sınıfının bir yöntemidir, yani kullanıcının kendi uygulamalarını herhangi bir tür için sağlamasına izin verilir - bu nedenle eğimliyseniz [Char] -> b dahil.

Hata mesajı, yazdığınız şeyin anlamsız olduğunu size söylemek yerine, Haskell'in size, Num b => [Char] -> b türünü nasıl oluşturduğunuzu öğretmediğinizi anlatması anlamına gelir, çünkü bu ihtiyaç duyacağınız gerçekten tuhaf bir şeydir ifadenin anlamlı olması için doğru olmak.