我有以下类型类(省略了不相关的方法):
class Initializable a where
initialize :: IO a
initialize = return initializePure
{# convenience method for implementations, not to be called from outside #}
initializePure :: a
data Foo = Foo
instance Initializable Foo where
initializePure = Foo
data Bar = Bar
instance Initializable Bar where
initialize = initializeBar
Run Code Online (Sandbox Code Playgroud)
有些实现需要IO初始化自己,有些则不需要.
此代码发出警告:
No explicit implementation for
‘initializePure’
In the instance declaration for ‘Initializable Bar’
Run Code Online (Sandbox Code Playgroud)
我试图添加这样的MINIMALpragma:
{-# MINIMAL initializePure | initialize #-}
Run Code Online (Sandbox Code Playgroud)
但后来我得到了一个不同的警告:
The MINIMAL pragma does …Run Code Online (Sandbox Code Playgroud) 当一个函数出现在monad中时,它会发生一些变化.
在GHCI中:
> :t map
map :: (a -> b) -> [a] -> [b]
> a <- return map
> :t a
a :: (GHC.Prim.Any -> GHC.Prim.Any)
-> [GHC.Prim.Any] -> [GHC.Prim.Any]
Run Code Online (Sandbox Code Playgroud)
此更改使得难以将函数存储在更高级别的类型中.
这里发生了什么,我可以让它不会发生吗?
(这也不违反monad法律之一吗?)
我正在为我创建的数据类型编写一个"附加"函数(基本上处理"流").但是,这种数据类型有12种不同的构造函数,处理不同类型的"流",例如,无限,空,固定长度,可变长度,已经附加等.
输入类型和输出类型之间的逻辑有点复杂但并非如此令人难以置信.
我考虑过两种方法:
我知道第二种方法更难以维护,但忽视这一点,GHC会发现第二种方法更容易优化吗?如果它可以使用简单的跳转表(或者可能是两个跳转表)进行第二种方法,我怀疑它会更快.但是,如果它进行线性检查,它将会慢得多.
GHC是否将模式匹配(甚至非常大的匹配)优化为恒定时间跳转表?
我想在Haskell中使用Aeson解析以下JSON:
{
"foo": {
"name": "name 1",
"location": "location 1"
},
"bar": {
"name": "name 2",
"location": "location 2"
}
}
Run Code Online (Sandbox Code Playgroud)
按键name和location是已知的,但foo和bar未知.
我想将JSON数据加载为以下数据类型([Entry])的列表:
data Entry = Entry
{ id :: String -- "foo" or "bar" etc.
, name :: String -- "name 1" or "name 2" etc.
, location :: String -- "location 1" or "location 2" etc.
} deriving Show
Run Code Online (Sandbox Code Playgroud)
我的第一次尝试看起来如下(它不起作用):
instance FromJSON Entry where
parseJSON (Object o) = …Run Code Online (Sandbox Code Playgroud) 假设我有一个定义为的数据类型
data Foo = Hello Int | World Int
Run Code Online (Sandbox Code Playgroud)
和作为
isWorld :: Foo -> Bool
isWorld (World i) = True
isWorld (Hello i) = False
getWorlds :: Set Foo -> Set World
getWorlds = Set.filter isWorld
Run Code Online (Sandbox Code Playgroud)
这不起作用:
Not in scope: type constructor or class `World'
Run Code Online (Sandbox Code Playgroud)
这是有道理的,因为World它只是一个函数,但我不知道如何在Haskell中对此进行建模.使用data正确吗?我希望能够仅为某些实例定义函数:
foo :: World -> Int
foo (World i) = i
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,这会产生同样的错误,因为World它不是一种类型.有没有办法做到这一点,最好没有GHC扩展?
最近我做了一个程序,我使用了以下形式的数据类型:
data MyType = Constructor1 | Constructor2 deriving Eq
Run Code Online (Sandbox Code Playgroud)
是的,这种类型实际上与Bool我刚才命名的不同,以使我的代码更具可读性.在程序的后期,我有表格的功能
myFunc input = if input == Constructor1 then --do something
else --do something else
Run Code Online (Sandbox Code Playgroud)
我认为这可能是一个坏主意的原因是,如果它被解释为它的方式,每次程序遇到这个分支时,它必须运行==它设置的函数MyType来获得Bool通过对于该if_then_else_功能,如果我刚刚使用Bool该==功能的必要性被消除,这将加快该过程.
我应该替换所有实例的MyType实例,Bool还是ghc以某种方式优化数据类型的使用?
我最近参加了竞争性的编码竞赛.
这个Haskell在运行ghc 7.6.3的判断系统上发生了空间泄漏:
t n [] = 0
t n ('8':rest) = t (n+1) rest
t n (')':rest) = n + (t n rest)
main = getLine >>= (\l -> print (t 0 l))
Run Code Online (Sandbox Code Playgroud)
比赛结束后,测试用例发布.其中一个失败案例是:(一个包含10 ^ 5个关闭的parens的文件):https://cses.fi/download/1/b575d19a75bf724b50fa4a399f8187b6d6edb4ccb62bd1a774f9294969152e46
错误是
Stack space overflow: current size 8388608 bytes. Use `+RTS -Ksize -RTS' to increase it.
Run Code Online (Sandbox Code Playgroud)
我也知道代码是用-O2和-Wall编译的,我认为是GHC 7.6.3.
对于我的生活,我无法在我的机器上使用GHC 8.0.2或7.10.3重现错误.
代码中是否有明显的空间泄漏?
编辑:
我测试了下面建议的代码和这样实现的折叠:
import Data.Foldable
t (kasit, score) '8' = (kasit+1, score)
t (kasit, score) _ = (kasit, score+kasit)
main = …Run Code Online (Sandbox Code Playgroud) 如果我有一个类似的程序
main = print ( (+) <$> Just 1 <*> Just 2 )
将编译器决定减少我的程序,它不依赖于的部分IO像
( (+) <$> Just 1 <*> Just 2 ) => (Just 3)?
或者程序是否仍然创建一个新函数(+) <$> Just 1,然后Just 2在运行时应用它?
我一直在做一些构建我自己的自定义前奏的工作,我想构建一个Callable类型类,它将($)为函数以外的类型实现函数application().所以我使用多参数类型类构建了一个类型类:
{-# Language MultiParamTypeClasses #-}
import Prelude ()
class Callable a b c where
($) :: a -> b -> c
Run Code Online (Sandbox Code Playgroud)
现在我继续将函数作为Callable类型类的实例,这需要我启用灵活的实例.
{-# Language MultiParamTypeClasses, FlexibleInstances #-}
import Prelude ()
id :: a -> a
id x = x
class Callable a b c where
($) :: a -> b -> c
instance Callable (a -> b) a b where
($) = id
Run Code Online (Sandbox Code Playgroud)
这很好,现在我可以($)在函数上使用.因此,对我来说,下一个合乎逻辑的步骤是实现函数组合((.)).经过一段时间的努力,我意识到为了做到这一点,我需要在Callable功能上依赖,所以我打开了功能依赖.
{-# Language MultiParamTypeClasses, FlexibleInstances, …Run Code Online (Sandbox Code Playgroud)