我注意到,在进行codegolf挑战时,默认情况下,GHC不会推断变量的最常规类型,当您尝试使用两种不同类型时会导致类型错误.
例如:
(!) = elem
x = 'l' ! "hello" -- From its use here, GHC assumes (!) :: Char -> [Char] -> Bool
y = 5 ! [3..8] -- Fails because GHC expects these numbers to be of type Char, too
Run Code Online (Sandbox Code Playgroud)
这可以使用pragma进行更改NoMonomorphismRestriction.
但是,将此键入GHCI不会产生类型错误,并且:t (!)在此处显示(Foldable t, Eq a) => a -> t a -> Bool,即使显式运行,也会假设-XMonomorphismRestriction.
为什么GHC和GHCI在假定最常用的函数类型方面有所不同?
(另外,为什么默认启用它?它有什么帮助?)
有一件事,让我早卡住时学习Haskell是之间的差异foldl +和foldl (+).
Prelude> :t foldl + 0 [1,2,3]
:: (Num t1, Num ((b -> a -> b) -> b -> t a -> b),
Num ([t1] -> (b -> a -> b) -> b -> t a -> b), Foldable t) =>
(b -> a -> b) -> b -> t a -> b
Run Code Online (Sandbox Code Playgroud)
VS
Prelude> :t foldl (+) 0 [1,2,3]
foldl (+) 0 [1,2,3] :: Num b => b
Run Code Online (Sandbox Code Playgroud)
Haskell/GHC如何得出这种类型foldl + 0 [1,2,3] …
我已经找到了将a Nat转换为Integer使用的方法Proxy,natVal您可以在下面的代码中看到:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Main where
import Data.Proxy (Proxy)
import Data.Monoid ((<>))
import GHC.TypeLits
main :: IO ()
main = do
fromNat (undefined :: Proxy 5)
fromNat :: KnownNat n => Proxy n -> IO ()
fromNat proxy = do
let (num :: Integer) = natVal proxy -- converting a Nat to an Integer
putStrLn $ "Some num: " <> show num
Run Code Online (Sandbox Code Playgroud)
但是我无法想出将类型列表转换为常规列表的简单方法,下面的代码甚至不会键入check:
{-# LANGUAGE DataKinds …Run Code Online (Sandbox Code Playgroud) 如果一个线程等待MVar没有可能的生成器,那么GHC通常足够聪明,可以抛出BlockedIndefinitelyOnMVar并杀死该线程.这个检测是如何实现的?
它是否检查所有对a的引用MVar是来自等待它的线程,还是类似的东西?
以下函数通过使用递归方案库从列表实现良好的旧过滤器函数.
import Data.Functor.Foldable
catafilter :: (a -> Bool) -> [a] -> [a]
catafilter p = cata alg
where
-- alg :: ListF a [a] -> [a]
alg Nil = []
alg (Cons x xs) = if (p x) then x : xs else xs
Run Code Online (Sandbox Code Playgroud)
它编译和短期测试就像catafilter odd [1,2,3,4]是成功的.但是,如果我取消注释类型签名,alg我会收到以下错误:
src/cata.hs:8:30: error:
• Couldn't match expected type ‘a’ with actual type ‘a1’
‘a1’ is a rigid type variable bound by
the type signature for:
alg …Run Code Online (Sandbox Code Playgroud) 在ghci(8.2)上,
:k ('[] :: [(Type,Type)])
Run Code Online (Sandbox Code Playgroud)
成功,但是
:k ('[(Bool,Bool)] :: [(Type,Type)])
Run Code Online (Sandbox Code Playgroud)
不,因为(Bool,Bool)(甚至像('True,False')这样的东西都有种类*.
我理解问题在于(,)构造函数,它构造了一个*Type.
表示类型级强类型对的列表的方法是什么?
考虑以下功能:
foo :: Show a => Maybe a -> [Char]
foo (Just x) = show x
foo Nothing = "Nothing"
Run Code Online (Sandbox Code Playgroud)
然后我尝试使用这个功能:
bar :: [Char]
bar = foo Nothing
Run Code Online (Sandbox Code Playgroud)
已传递给参数foo的类型是Maybe a其中a没有指定,而事实上,我们不关心a,因为我们只使用的情况下foo进行的Nothing.但GHC声称提供具体类型:
a0由于使用而产生的模糊类型变量foo
可防止约束(Show a0)被解决.可能的修复:使用类型注释来指定a0应该是什么.
GHC提示指定类型.所以我看到的唯一修复就是创建一个伪类型,它有一个Show类型为class 的实例:
{-# LANGUAGE EmptyDataDecls, KindSignatures #-}
{-# OPTIONS_GHC -fno-warn-missing-methods #-}
data Dummy :: *
instance Show Dummy
bar :: [Char]
bar = foo (Nothing :: Maybe …Run Code Online (Sandbox Code Playgroud) 在运行GHC编译的程序时,我经常会在GC中花费大量的周期。
这些数字往往比我的JVM经验所建议的高几个数量级。特别是,GC“复制”的字节数似乎比我正在计算的数据量大得多。
非严格语言和严格语言之间的这种区别是根本的吗?
到目前为止,我已经尝试了以下方法:
me@pc:~/code$ ghc file.hs -Wall | tee warnings.log
me@pc:~/code$ ghc file.hs -Wall > warnings.log
Run Code Online (Sandbox Code Playgroud)
但是ghc只像正常情况那样打印警告,并且仅通过非警告步骤。
有没有办法做到这一点?
我只是刚开始使用Haskell和函数式编程。编译并运行我的第一个Haskell程序后,我注意到(在Linux上)GHC从单个.hs源文件生成三个单独的文件:.hi文件,.o文件以及最后一个可执行文件。这些文件的目的是什么?实际上,何时实际使用.hi和.o文件?
根据我在C语言方面的小经验,我认为.o是一个目标文件。搜索Google表示.hi是“接口文件”。