我想有一个类型可以包含0到n的值,其中n存在于类型级别.
我在尝试这样的事情:
import GHC.TypeLits
import Data.Proxy
newtype FiniteNat n = FiniteNat { toInteger :: Integer }
smartConstructFiniteNat :: (KnownNat n) => Proxy n -> Integer -> Maybe (FiniteNat (Proxy n))
smartConstructFiniteNat pn i
| 0 <= i && i < n = Just (FiniteNat i)
| otherwise = Nothing
where n = natVal pn
Run Code Online (Sandbox Code Playgroud)
这基本上是有效的,但它并不是真的令人满意.是否有"标准"解决方案,甚至是图书馆来实现这一目标?关于依赖类型列表长度有很多大惊小怪,但我无法找到完全符合此类的东西.另外 - 我认为使用GHC.TypeLits
是必要的,因为我n
可以采用相当大的值,因此归纳定义可能会非常慢.
我的理解Sum
和Product
newtypes是它们用于数值类型为monoidial包装.我想了解Functor
他们的实例,但为什么还有Applicative
,Monad
任何其他许多看似无用的情况下?我知道它们在数学上是可以的(与Identity
modad 同构,对吧?)但是用例是什么?Applicative Sum
例如,如果存在实例,我希望在Sum (a -> b)
某处遇到类型的值.我无法想象这可能有用的地方.
Haskell 中有一个简单的列表函数可用
iterate :: (a -> a) -> a -> [a]
iterate f x = x : iterate f (f x)
Run Code Online (Sandbox Code Playgroud)
在Python中可以按如下方式实现:
def iterate(f, init):
while True:
yield init
init = f(init)
Run Code Online (Sandbox Code Playgroud)
我有点惊讶像这样的基本东西不是 functools/itertools 模块的一部分。是否可以使用这些库中提供的工具以函数式风格(即没有循环)简单地构建它?(主要是代码高尔夫,试图了解 Python 中的函数式风格。)
以下typechecks:
instance (Applicative f, Alternative f, Foldable f) => Monad f where
(>>=) = flip $ \f -> foldr (<|>) empty . fmap f
-- Or equivalently
a >>= b = getAlt . foldMap Alt . fmap b $ a
Run Code Online (Sandbox Code Playgroud)
这实际上是一个有效的Monad
实例吗?如果是,为什么不使用它?如果不是,它是否违反任何法律等?我没有证明法律适用,但我也找不到反例.
我想有一个功能
powersetWithComplements :: [a] -> [([a], [a])]
Run Code Online (Sandbox Code Playgroud)
例如:
powersetWithComplements [1,2,3] = [([],[1,2,3]),([3],[1,2]),([2],[1,3]),([2,3],[1]),([1],[2,3]),([1,3],[2]),([1,2],[3]),([1,2,3],[])]
Run Code Online (Sandbox Code Playgroud)
例如,很容易获得一些实现
powerset :: [a] -> [[a]]
powerset = filterM (const [False, True])
powersetWithComplements s = let p = powerset s in zip p (reverse p)
Run Code Online (Sandbox Code Playgroud)
要么
powersetWithComplements s = [ (x, s \\ x) | x <- powerset s]
Run Code Online (Sandbox Code Playgroud)
但我估计这两者的表现都会很差.什么是最佳方法?可以使用与[]
列表不同的数据结构.
许多Python内置的"函数"实际上是类,尽管它们也有简单的函数实现.甚至非常简单,例如itertools.repeat
.这是什么动机?这对我来说似乎过度工程化了.
编辑:我不是在询问其目的itertools.repeat
或任何其他特定功能.它只是一个非常简单的函数的示例,具有非常简单的可能的实现:
def repeat(x):
while True: yield x
Run Code Online (Sandbox Code Playgroud)
但itertools.repeat
实际上它不是一个函数,它是作为一个类实现的.我的问题是:为什么?这似乎是不必要的开销.
另外我理解类是可调用函数,以及如何使用类模拟类函数行为.但我不明白为什么它通过标准库如此广泛使用.
我正在学习monad变形金刚,我很困惑在使用电梯时是必要的.假设我有以下代码(它没有做任何有趣的事情,只是我可以带来的最简单的演示).
foo :: Int -> State Int Int
foo x = do
(`runContT` pure) $ do
callCC $ \exit -> do
when (odd x) $ do
-- lift unnecessary
a <- get
put $ 2*a
when (x >= 5) $ do
-- lift unnecessary, but there is exit
a <- get
exit a
when (x < 0) $ do
-- lift necessary
a <- lift $ foo (x + 10)
lift $ put a
lift get
Run Code Online (Sandbox Code Playgroud)
所以有一个monad堆栈,其中主要的块有类型ContT Int (StateT …
这是我的代码.该程序获得一些点坐标,它应该枚举所有路径(将来应该更复杂,但这是本质)
#include <iostream>
#include <utility>
#include <vector>
#include <iterator>
#include <algorithm>
#include <cmath>
using namespace std;
struct Point {
Point () {};
Point (const int &x_, const int &y_) : x{x_}, y{y_} {};
int x, y;
};
double distance(const Point &a, const Point &b) {
return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2));
}
struct Path {
vector<Point> points;
double length;
Path(vector<Point> &p) : points{p}, length{0.0} {};
void add_point(Point &p) {
length += distance(p, points.back());
points.push_back(p);
}
}; …
Run Code Online (Sandbox Code Playgroud) 我有以下程序:
{-# LANGUAGE TemplateHaskell #-}
import qualified Data.Map.Strict as Map
import Control.Lens
data MyLabel = MyLabel { _label :: String } deriving (Show, Eq, Ord)
data MyMap = MyMap { _vals :: Map.Map String MyLabel } deriving (Show, Eq, Ord)
makeLenses ''MyLabel
makeLenses ''MyMap
sample :: MyMap
sample = MyMap { _vals = Map.fromList [("foo", MyLabel "bar")] }
Run Code Online (Sandbox Code Playgroud)
现在我想知道如何f
使用镜头进行转换,以便:
f sample "quux" == MyMap { _vals = Map.fromList [("foo", MyLabel "quux")] }
Run Code Online (Sandbox Code Playgroud)
我了解到at
Lens库中的函数应该用于修改Maps,所以我试图做这样的事情:
sample ^. vals …
Run Code Online (Sandbox Code Playgroud) 假设我有这样的类型:
data Graph vertex = Graph {
vertices :: [vertex],
edgelist :: [(vertex, [vertex])]
}
Run Code Online (Sandbox Code Playgroud)
但是我想在类型变量顶点上有一个类型类约束,我试图像使用类型类定义那样做:
data (Eq vertex) => Graph vertex = Graph {
vertices :: [vertex],
edgelist :: [(vertex, [vertex])]
}
Run Code Online (Sandbox Code Playgroud)
但这会产生语法错误Illegal datatype context (use DatatypeContexts)
.实现这一目标的正确方法是什么?还是不可能?
我有一些功能
bar :: MyType -> MyType -> [MyType]
Run Code Online (Sandbox Code Playgroud)
我想有另一个功能:
foo :: [MyType] -> [MyType]
foo xs = do x <- xs
y <- xs
bar x y
Run Code Online (Sandbox Code Playgroud)
是否可以在foo
不使用do
符号的情况下编写?我在考虑类似的东西,liftA2
但那不起作用.
haskell ×9
monads ×3
typeclass ×3
python ×2
c++ ×1
c++11 ×1
class ×1
dictionary ×1
do-notation ×1
haskell-lens ×1
idris ×1
iteration ×1
lifting ×1
linked-list ×1
memory ×1
powerset ×1