只是一个随机的思考,看着我的无数次length调用,我发现编译器可以通过不变性和引用透明度来判断任何列表的长度(即使新的列表concat来自现有的已知列表/代码路径).那么它可能会在低级代码生成期间的某个阶段length l用实际的 int常量替换所有"调用" ,对吗?
想知道它是否确实存在,或者我是否在初学者中缺少关于纯函数式语言/编译器的东西.
我用(^) :: (Num a, Integral b) => a -> b -> a了很多来定义常数因子或大小.问题是GHC抱怨默认为Integer.
现在我知道为什么会发生这种情况......我知道我可以"只是"写出(x^(y::Int))去除警告.但这看起来只是"丑陋".生活在警告中的奥托也不是一个好选择.
同样的事情适用于我(^^) :: (Integral b, Fractional a) => a -> b -> a并且(**) :: Floating a => a -> a -> a不适用于我.
任何人都有一个很好的解决这个(第一世界)的问题?
刚刚发现这个宝石的代码:
alignment a = 2 ^ ceiling (logBase 2 (fromIntegral (sizeOf a)))
Run Code Online (Sandbox Code Playgroud)
这是一个LOC和GHC抱怨默认Integer和Double在同一条线上.
在使用GHC编译后运行时,我有以下代码似乎一直挂起(尽管没有构建失败-Werror).
import Data.Aeson
import Data.Scientific
import qualified Data.HashMap.Strict as S
myObj = Object $
S.fromList [("bla", Number $ pc * 100.0)]
where pc = 10 / 9
Run Code Online (Sandbox Code Playgroud)
而当试图访问myObj该程序将挂起.经过一些挖掘后,似乎haskell在数字转换方面遇到了困难(尽管上面的代码片段没有警告或错误).如果我将9上面的内容更改为a 10,则不会挂起.但我很好奇,为什么上面挂了?
我正在尝试仅使用Prelude库中的函数在两个数字列表之间实现点积.我写了以下函数:
dot :: Num a => [a] -> [a] -> a
dot x y = sum $ zipWith (*) x y
Run Code Online (Sandbox Code Playgroud)
我测试如下:
main :: IO ()
main = do
let n = 10^6
x = (replicate n 2.0) :: [Double]
y = (replicate n 3.0) :: [Double]
print $ dot x y
return ()
Run Code Online (Sandbox Code Playgroud)
不幸的是,这段代码导致了包含100万个元素的列表的堆栈空间溢出(使用ghc 7.6.3和优化标志-O2).
对于这种简单的情况,我希望ghc能够执行必要的优化以避免递归调用的成本.我错过了什么吗?我的实施错了吗?
我Functor为我的自定义Either类型编写了一个实例Or,它的工作原理就像这样:
data Or a b = First a
| Second b
deriving (Eq, Show)
instance Functor (Or a) where
fmap _ (First x) = First x
fmap f (Second b) = Second $ f b
Run Code Online (Sandbox Code Playgroud)
然而,当我使用as-pattern时,该程序不再进行类型检查:
instance Functor (Or a) where
fmap _ first@(First _) = first
fmap f (Second b) = Second $ f b
Run Code Online (Sandbox Code Playgroud)
错误消息:
error:
• Couldn't match type ‘a1’ with ‘b’
‘a1’ is a rigid type variable bound by
the …Run Code Online (Sandbox Code Playgroud) 我试图在Haskell中定义自然数乘法,并继续得到下面的错误(对应于下面的第二个natMult定义).
Prelude> natMult (S (S Z)) (S (S Z))
*** Exception: <interactive>:(4,5)-(5,45): Non-exhaustive patterns in function natPlus
Run Code Online (Sandbox Code Playgroud)
这是我的代码:
data Nat = Z | S Nat deriving (Show)
natPlus :: Nat -> Nat -> Nat
natPlus Z a = a
natPlus (S a) (S b) = natPlus a (S (S b))
Run Code Online (Sandbox Code Playgroud)
经过一些修修补补后,我意识到这个定义工作正常,而下面的第二个定义则被打破了.唯一的区别是natPlus的输入参数的顺序.
-- works fine
natMult :: Nat -> Nat -> Nat
natMult Z a = Z
natMult (S a) b = natPlus (natMult a b) b
-- gives gives the …Run Code Online (Sandbox Code Playgroud) 我有以下用例:我正在构建一个自定义AST.作为我在AST上进行的某些操作的优化,我已经为AST节点定义了一个子列表,因此:
data NodeChHolder a = NNode [a] -- For "normal" operators
| ACNode (MultiSet a) -- For operators that can be re-ordered and parenthesized arbitrarily
| NCNode -- Empty, no children
Run Code Online (Sandbox Code Playgroud)
现在,我想让这个类型成为Functor.但是,有一个问题,因为MultiSet需要它的类型参数Ord.所以,这不起作用:
instance Functor NodeChHolder where
fmap f (NNode l) = NNode $ map f l
fmap f (ACNode s) = ACNode $ MultiSet.map f s
fmap _ NCNode = NCNode
Run Code Online (Sandbox Code Playgroud)
我得到一个错误,说"使用MultiSet.map"没有"Ord b的实例",这是公平的.
为解决此问题,我尝试使用ScopedTypeVariablesghc扩展的以下方法.我认为这类似于它如何与类型一起工作,但似乎类型类不同:
instance Functor NodeChHolder where
fmap f (NNode l) = NNode …Run Code Online (Sandbox Code Playgroud) 尝试使用"堆栈构建"构建:
module Main where
analyzeGold :: Int -> String
analyzeGold standard =
if | standard == 999 -> "Wow! 999 standard!"
| standard == 750 -> "Great! 750 standard."
| standard == 585 -> "Not bad! 585 standard."
| otherwise -> "I don't know such a standard..."
main :: IO ()
main = do
putStrLn (analyzeGold 999)
Run Code Online (Sandbox Code Playgroud)
我得到了:
Multi-way if-expressions need MultiWayIf turned on
|
6 | if | standard == 999 -> "Wow! 999 standard!"
| ^^
Run Code Online (Sandbox Code Playgroud)
怎么解决?
堆栈1.7.1,GHC …
假设我有一个包含10个元素的简单枚举类型:
data Test = A | B | C | D | E | F | G | H | I | J
deriving Eq
Run Code Online (Sandbox Code Playgroud)
GHC Eq按照您的预期派生实例:
==================== Derived instances ====================
Derived class instances:
instance GHC.Classes.Eq Test.Test where
(GHC.Classes.==) (Test.A) (Test.A) = GHC.Types.True
(GHC.Classes.==) (Test.B) (Test.B) = GHC.Types.True
(GHC.Classes.==) (Test.C) (Test.C) = GHC.Types.True
(GHC.Classes.==) (Test.D) (Test.D) = GHC.Types.True
(GHC.Classes.==) (Test.E) (Test.E) = GHC.Types.True
(GHC.Classes.==) (Test.F) (Test.F) = GHC.Types.True
(GHC.Classes.==) (Test.G) (Test.G) = GHC.Types.True
(GHC.Classes.==) (Test.H) (Test.H) = GHC.Types.True
(GHC.Classes.==) …Run Code Online (Sandbox Code Playgroud) 所以我有这个:
lstDelete :: [Char] -> Lst a -> Lst a
lstDelete k inp@(lstNode key)
| k == key && lstIsEmpty = Map.delete key (Map.fromList inp)
Run Code Online (Sandbox Code Playgroud)
问题是,k的类型为[Char],键的类型为(Maybe a):
data Lst a = lstNode (Maybe a)
Run Code Online (Sandbox Code Playgroud)
所以我收到的错误是:
Couldn't match expected type ‘[Char]’ with actual type ‘Maybe a’
Run Code Online (Sandbox Code Playgroud)
如何在不改变的情况下修复此问题lstDelete :: [Char] -> Lst a -> Lst a?我也想保留,Maybe a因为我希望它也可以是空的.