System.Info'ya erişmek neden Haskell'de bir IO işlemi olarak kabul edilmiyor?


25

Modülde System.Infoşu işlevleri görüyorum:

os :: String
arch :: String
compilerName :: String
compilerVersion :: Version

Neden orada yok IO? Sisteme erişiyorlar ... Yanlış mıyım? Benim beklentim şöyleydi:

os :: IO String
arch :: IO String
compilerName :: IO String
compilerVersion :: IO Version

Kullanım örneği:

      print os            -- "darwin"
      print arch          -- "x86_64"
      print compilerName  -- "ghc"

Yanıtlar:


29

Bu bilgiyi çalışma zamanında almıyorsunuz . Derleyiciye sisteminizde kurulu olarak kodlanmıştır.

Bu, http://hackage.haskell.org/package/base-4.12.0.0/docs/src/System.Info.html adresindecompilerName bulunan tanıma bakarsanız çok açıktır .

compilerName :: String
compilerName = "ghc"

ama böyle bir şey bile os

os :: String
os = HOST_OS

, başka türlü tanımlanmamış bir ad HOST_OS(büyük harfle başlayan bir değer ??) olarak tanımlanır; bu, yalnızca yükleme sırasında değiştirilen bir yer tutucu olduğunu gösterir.

Birisi de beni düzeltebilir (lütfen!), Ancak {-# LANGUAGE CPP #-}bu dosyanın üstündeki pragma, HOST_OSderlemeden önce ve benzerlerinin C ön işlemcisi tarafından uygun dizelerle değiştirildiğini gösterir.


2
OP gerçekten IOorada biraz istiyorsa uname(3), Hackage'da bir paket var: hackage.haskell.org/package/bindings-uname
thsutton

19

Soru iyi bir soru. Yanıt, olduğu gibi, bu değerlerin program derlemesi başına statik olmasıdır. Esasen programa derlenirler ve bundan sonra asla değişmezler. Bu nedenle, sabit olarak kabul ederseniz hiçbir şey (GHC'nin kullandığı varsayımlarda) bozulmaz. Ve bir IO eyleminden daha basit bir sabit kullanmak daha uygundur.

Ama bu bir tür miras mantığı. Haskell eski bir dildir. (Hayır, aslında birkaç yıl Java'dan daha eski.) Artık en iyi uygulamalar olarak kabul edilmeyen akıl yürütme ile birçok kütüphane inşa edildi. Bunlar bunun örnekleridir. Bunları ortaya çıkaran modern bir kütüphane, derlemeden sonra sonuçlar değişmese bile muhtemelen IO eylemleri yapacaktır. Sabit seviyede olmayan şeyleri IO eylemlerinin arkasına koymak daha yararlıdır, ancak yine de Int32 ve 64 bit platformlar arasında boyut değiştirmek gibi bazı önemli istisnalar vardır .

Her durumda ... Beklentilerinizin sağlam olduğunu ve bu türlerin tarihsel tuhaflıkların sonuçları olduğunu söyleyebilirim.


-9

DÜZENLEME: @interjay ve @Antal Spector-Zabusky'ye bu cevabın neden reddedildiğini açıkladıkları için teşekkürler. Yazdılar

Dokümantasyon biraz yanıltıcı. Değerler GHC derleyicisine kodlanmıştır. 48 yıl sonra, gerçek kodun her zaman belgeleri koyduğunu bilirsiniz. - interjay yesterday @ andy256 Belgelerin kötü olduğu konusunda kesinlikle haklısınız (gerçekten, Francisco'nun bu soruyu ilk başta neden sorduğunun bir parçası) ve karışıklığınız anlaşılabilir. Haskell ile ilgili şey, bu String değerleri çalışma zamanında değişebiliyorsa, bu korkunç bir hata olacaktır - değişkenlerin değişmesine izin verilmez. Bu, IO tipi kurucunun önemidir - "dış dünyaya" erişmesine izin verilen ve böylece sonucu değişebilen bir hesaplamayı temsil eder. Sistem çağrısı yapmak bir ES eylemine iyi bir örnektir. … [1/2] - Antal Spector-Zabusky 9 saat önce @ andy256… (Başka bir IO eylemi "küresel bir sayacı güncellemek" olabilir.) Yani bir String gördüğümüzde bunun herhangi bir iletişim kuramayacağını biliyoruz. OS altında. Bu nedenle, belki de şaşırtıcı bir şekilde Haskell'e alışkın değilseniz, bir sistem çağrısı yapmak için os :: String'i uygulamak kolay olmaz - bu tür bir değer temel Haskell'de uygulanamaz, her programcının programların nasıl olacağı beklentisini ihlal eder ve hatta derleyici ve optimize ediciyi açabilirsiniz (teorik bir endişe değil - insanların benzer problemlerle karşılaştığı Yığın Taşması cevapları vardır). [2/2] - Antal Spector-Zabusky Bu nedenle, belki de şaşırtıcı bir şekilde Haskell'e alışkın değilseniz, bir sistem çağrısı yapmak için os :: String'i uygulamak kolay olmaz - bu tür bir değer temel Haskell'de uygulanamaz, her programcının programların nasıl olacağı beklentisini ihlal eder ve hatta derleyici ve optimize ediciyi açabilirsiniz (teorik bir endişe değil - insanların benzer problemlerle karşılaştığı Yığın Taşması cevapları vardır). [2/2] - Antal Spector-Zabusky Bu nedenle, belki de şaşırtıcı bir şekilde Haskell'e alışkın değilseniz, bir sistem çağrısı yapmak için os :: String'i uygulamak kolay olmaz - bu tür bir değer temel Haskell'de uygulanamaz, her programcının programların nasıl olacağı beklentisini ihlal eder ve hatta derleyici ve optimize ediciyi açabilirsiniz (teorik bir endişe değil - insanların benzer problemlerle karşılaştığı Yığın Taşması cevapları vardır). [2/2] - Antal Spector-Zabusky ve hatta derleyici ve optimize ediciyi bile açabilirsiniz (teorik bir endişe değil - insanların benzer problemlerle karşılaştığı Yığın Taşması cevapları vardır). [2/2] - Antal Spector-Zabusky ve hatta derleyici ve optimize ediciyi bile açabilirsiniz (teorik bir endişe değil - insanların benzer problemlerle karşılaştığı Yığın Taşması cevapları vardır). [2/2] - Antal Spector-Zabusky

Şu anda iki silme oyu var. Bu sürecin ilerlemesine izin vereceğim, ancak aslında bir değeri olduğunu öneriyorum. Bir yan notta, açıklamaları sorunun zayıf olduğunu ve cevapların da olduğunu gösteriyor, çünkü Haskell acemi yaptığım mantığı kolayca takip edebiliyordu.

Orijinal cevap:

Ben bir Haskell programcısı değilim, ancak verilen iki cevap OP'nin bağladığı belgelerle eşleşmiyor.

Belgelerimi yorumlamam şu şekildedir.

os :: String - Bu size "Programın üzerinde çalıştığı işletim sistemi" ni verir.

Bunun bilgi almak için sistem çağrısı yapmasını bekliyorum. Programın derlendiği sistem, üzerinde çalıştığı sistemden farklı olabileceğinden, derleyici tarafından eklenen bir değer olamaz. Kod yorumlanıyorsa, yorumlayıcı bir sistem çağrısı yoluyla alınması gereken sonucu sağlayabilir.

arch :: String - Bu size "Programın üzerinde çalıştığı makine mimarisini" verir.

Yine, bunun bilgi almak için bir sistem çağrısı yapacağını umuyorum. Programın derlendiği sistem, üzerinde çalıştığı sistemden farklı olabileceğinden, derleyici tarafından eklenen bir değer olamaz.

compilerName :: String - Bu size "Programın derlendiği veya yorumlandığı Haskell uygulaması" verir.

Bu değer derleyici / yorumlayıcı tarafından kesinlikle eklenir.

compilerVersion :: String - Bu size " compilerName Programın derlendiği veya yorumlandığı .

Bu değer derleyici / yorumlayıcı tarafından kesinlikle eklenir.

İlk iki çağrıyı girdi olarak değerlendirseniz de, sonuç İşletim Sistemi tarafından tutulan değerlerden gelir. G / Ç genellikle ikincil depolama alanına erişim anlamına gelir.


3
Haskell için bu doğru değil. Burada herhangi bir hesaplama sıralanmamıştır ve sonuçları önbelleğe alınabilir. İşlevler saftır, bu nedenle işlev hiçbir argümanı kabul etmezse, bir sabite çok benzer. Bir bağımsız değişkenin işlevleri, değeri anahtara göre hesaplayan hashmaps veya sözlüklere benzer. Harici ortamı kullanamaz, bu tür işlevlerde sistem çağrıları yapamazsınız, rastgele bir sayı veya geçerli tarih bile alamazsınız. Ama aslında bu "sıralama" veya ortamı kullanmak istiyorsanız, o zaman IOdevlet taklit, operasyonlar dizisi taklit için monad kullanmanız gerekir
Yuri Kovalenko

"Harici ortamı kullanamazsınız, bu tür işlevlerde sistem çağrıları yapabilirsiniz" - Tabii ki, özellikle "siz" Haskell derleyicisi iseniz! Değerlendirildiğinde os :: Stringbir sistem çağrısı yapabilmesi için bir Haskell uygulamasının uygulanması çok kolay olacaktır .
Tanner Swett

2
Haskell'deki IO monadının önemini anladığınızı sanmıyorum.
Sneftel

@Sneftel Elbette haklısınız. Cevap vermeyi seçtim, çünkü her paradigmada 48 yıllık programlama ve tek derleyiciyi yazdıktan sonra, ilk cevaplar belgelere uymadı ve hala uymuyorlar. Bunu açıkça söylüyor osve archçalışma zamanında elde ediliyor.
andy256

1
Dokümantasyon biraz yanıltıcı. Değerler GHC derleyicisine kodlanmıştır. 48 yıl sonra, gerçek kodun her zaman belgeleri koyduğunu bilirsiniz.
interjay
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.